{
  "$type": "site.standard.document",
  "canonicalUrl": "https://justingarrison.com/blog/2022-12-06-mastodon-files-instance",
  "coverImage": {
    "$type": "blob",
    "ref": {
      "$link": "bafkreibj6mw46rulz6syvzrs5m66kssyiv6maud5aytv4g7olrzgbx6faa"
    },
    "mimeType": "image/png",
    "size": 89516
  },
  "description": "How to make a single user, publish only, mastodon instance with four json files and two pictures",
  "path": "/blog/2022-12-06-mastodon-files-instance",
  "publishedAt": "2022-12-06T14:00:00.000Z",
  "site": "at://did:plc:p7uix7mresfq4nfzxp3klgfa/site.standard.publication/3mmdn7mg2qm2d",
  "textContent": "Mastodon is built on the ActivityPub protocol which is based on Activity Streams which stores data in JSON Linked Data (JSON-LD).\nAll that means is Mastodon uses a lot of JSON that references other JSON.\nA Mastodon instance can serve those JSON documents any way it wants so long as they are UTF-8 encoded.\n\nWhy would you do this?\n\nThere are more than 17,000 Mastodon instances.\nWhy would you implement one with static files?\n\nThe first reason is security.\nArs Technica has a great article about some of the concerns with running large scale, multi-user social network servers.\nI have a lot of my own concerns about Mastodon that I'll save for a future post.\n\nThere are scalability challenges on multiple levels.\nThe size of databases and uploads is what most admins are concerned with, but number of active users and scale of a single user (e.g. celebrity, company, government) is what will really take down a social network.\nAn instance with 30,000 active users costs nearly $1900 per month.\n\nIf Mastodon is going to be adopted by the critical users it needs to grow, instances—many of which are run by volunteers—would be crushed under the operational and financial responsibility.\nGovernments and companies aren't going to join shared servers; they're going to run their own instances on the domains they already own.\nThe best way to scale and maintain a server is to not run one.\n\nCreate a server\n\nIf you want to watch how I created these files check out the video.\n\n{{< youtube id=\"pyB7AFsQoJs\" title=\"Create a Mastodon instance in just 2 files\" >}}\n\nSo let's create a Mastodon instance using JSON files.\nYou can see the files on GitHub.\n\nThe files are hosted at https://mastodon.jgarr.net so you can test this for yourself by searching for the user @justin@mastodon.jgarr.net\n\nYou only need 1 file but to make a more complete user we'll use these 6:\n 2 files to create a user\n 2 files to pretend we are popular\n 2 pictures to make it look pretty\n\nThe only required file is the user, but I wanted to show how easy it is to lie in the fediverse.\n\nHere are the files we'll be using.\n\nNow let's explain what they do.\n\nUser discovery\nWhen you're using Mastodon you can search for a user on any Mastodon instance with @user@domain.\nThis is a short hand format which relies on webfinger to translate a user at a domain into a standard URL.\n\nWhen you do this search your Mastodon server will query the external server\n\nYou can bypass webfinger if you know how to fetch the user's information directly.\nIf you search in Mastodon for https://mastodon.jgarr.net/justin you'll get the same user.\n\n<details>\n  <summary>Here's the full access log so you can see the request.</summary>\n\n</details>\n\nThe GET request technically uses the parameter resource=acct:justin@mastodon.jgarr.net but with this static file example we only have one user on the domain so we'll ignore that part.\nIf you want to have multiple users on the same domain you will have to handle parameters on the server side.\nMeaning, you can't do that with static files.\n\nThis request returns the file\n\nThis says where to go fetch the next JSON document at the /justin path.\nYour Mastodon server will then go fetch that object.\n\n<details>\n  <summary>Here's the full access log so you can see the request.</summary>\n\n</details>\n\nIf you look at the access log you'll notice the signature in the header.\nThis uses a keyId https://mastodon.social/actor#main-key which is the instance that searched for the user.\nThere's a signature which can be used to verify the correct server―or user―is making requests.\n\nIf you want to you can skip webfinger by searching for a user by their URL directly.\nIf you search in Mastodon for https://mastodon.jgarr.net/justin you'll get the same user.\n\nThat means we need 1 less file but it doesn't seem as magical as @justin@mastodon.jgarr.net\n\nThis returns our actual user document.\n\nIf you want to see your user's JSON document you can append .json to your user's URL (e.g. https://mastodon.social/@jgarr.json)\n\nNot everything in this example user document is required, but here's the first place we can lie about our account and make it look more legitimate.\n\nYou'll noticed the published date 2000-01-01T00:00:00Z which means we created an account long before Mastodon existed.\nNot a big deal, but it's completely unverified.\n\nWe also add an icon and image to the profile so it doesn't have the default image.\nThe images are completely optional, but it adds legitemacy to a federated account posing as a real user.\n\nBecause we own the domain and can lie about the accounts we can use a commonly misspelled domain or unicode to create fake accounts.\nWe could easily use any domain to make accounts like @charles@gov.co.uk or @tim@apple.ceo (both of these domains are currently available).\n\nMastodon puts the zero in zero trust.\nIn reality, any completely decentralized system—like the internet—only has trust through reputation, but in Mastodon you can fake a repulation.\n\nHere's what the profile looks like.\n\n!a screenshot of my fake user\n\nAfter the user is requested your Mastodon instance will automatically fetch /followers and /following.\nJust like other documents these are reference documents to the actual data documents, but the data isn't verified so we can lie again.\n\nYou'll notice this account has 1 million followers and follows 1 account.\nBoth of which are not possible because even if you click the follow button the instance cannot acknowledge your request and this account has no keys so it cannot follow any accounts.\n\n<details>\n  <summary>Here's the full access log so you can see the request.</summary>\n\n</details>\n\n<details>\n  <summary>Here's the full access log so you can see the request.</summary>\n\n</details>\n\n/following\n\n/followers\n\nMastodon never validates the data in /follower_accts that we claim holds our 1 million followers so we don't have to create that file.\n\nIf you click the follow button your Mastodon instance will send a POST request to /inbox with your user's key signature.\n\nUnlike the requests before, this request will use the mastodon.social user's signature and key instead of the instance actor account.\nMy instance _should_ connect back to the mastodon.social server to verify the user's signature, but you'll notice the status 404 because I didn't implement following or create an inbox file.\n\nEven though the status is 404 the requesting server still shows a follow request is sent.\nIf you cancel the request it will decrement the followers count.\n\nWhat doesn't work\nThose 6 files is all you need to create a Mastodon user.\nHere are some caveats you may have already noticed.\n\n Following doesn't work\n Posts don't work\n Only 1 user per domain\n\nYou _can_ create JSON objects with posts, replies, or anything you'd like, but Mastodon instances don't fetch posts from external users unless someone from that instance follows the user or has reposted one of their posts.\nI implemented a single post in the /outbox file so if you want to see how they are structured you can browse the source files.\n\nThe instance is supposed to fetch pinned posts, but I couldn't figure out how that is implemented.\nIf someone knows please reach out and let me know at my real mastodon account @jgarr@mastodon.social.\n\nNext, we'll give this instance some of the functionality that doesn't work.\nWe'll allow users to follow the account, and then let it create posts.",
  "title": "Mastodon instance with 6 files"
}