{
  "$type": "site.standard.document",
  "bskyPostRef": {
    "cid": "bafyreiauw4tgiubabredqnwv6yunvnu36nz5wokmrvtrsi5qiirtq42b6a",
    "uri": "at://did:plc:cwdkf4xxjpznceembuuspt3d/app.bsky.feed.post/3m6e6pafqtk27"
  },
  "canonicalUrl": "https://jack.is/posts/self-hosting-your-pds/",
  "description": "A writeup of gotchas and other fun stuff along the way of deploying a PDS",
  "path": "/posts/self-hosting-your-pds/",
  "publishedAt": "2025-11-24T06:18:20.000Z",
  "site": "at://did:plc:cwdkf4xxjpznceembuuspt3d/site.standard.publication/3mdrpafzz7c2m",
  "tags": [
    "atproto",
    "server"
  ],
  "textContent": "Bluesky is great (as evidenced by my multiple posts on it), but I wanted to own\nmy data more than it living on the Bluesky servers. Now I could have just used\nthe standard deployment as shown in the PDS repo,\nbut I wanted to do something a little more fitting my deployment practices.\n\nWhy\n\nA few years ago, I moved my webserver (what runs this site, my PDS, and lots of\nother services) to CentOS Stream back when that was still viable, then Rocky\nLinux as the new replacement when Stream sort of died off. Is it perfect, is it\nthe right way to do things? No, but it's what I prefer at this point. [^1]\n\nThe Problem: part one\n\nThe default Bluesky PDS is intended for being deployed on Ubuntu 20.04/22.04. It\nwill fail to deploy on anything other than those two distributions (even 24.04\nwhich also works but that's neither here nor there).\n\nSolutioning a problem\n\nWhile I was in the testing phase of deploying my PDS, I was using an Ubuntu\nserver that I could successfully deploy using the installer. I already use Caddy\nthough, so the compose file having Caddy dockerized is not _ideal_. Fixing that\nwas a pretty easy cleanup to get a proper pds.env file out of it, since\nthere's no canonical source outside of the installer. Now I had a relatively\nstandard PDS deployment using Docker, but using the Caddy service I use for\neverything else on my server.\n\nBest Practices?\n\nI have _opinions_ on the way Bluesky PBLLC has made the systemd unit for the PDS\nin GitHub. It deploys as a oneshot, so journalctl is not super useful,\nsystemctl will never show it as running, and it is generally just hard to set\nit as a dependency or a dependent of any other services due to it being oneshot.\n\nFixing this took me on a rabbit hole / detour on how to do it \"better\".[^2]\n\nEnter ~~Sandman~~ Podman\n\nI had been watching my coworkers explore Podman a bit at work, and looking into\nit, it had the perfect thing for my needs, the ability to \"systemd-ize\" a\ncontainer workload in a way that made sense for both the container, and for\nsystemd. I also took this opportunity to set up litestream\nfor backups as well.\n\nNow that everything's mostly stable, I can finally document all my configuration\nfor anyone else to use.\n\nUnder the hood it's using Quadlets,\nso all of the unit files we'll create in /etc/containers/systemd.\n\nFirst we create a pod to contain everything and publish the port:\n\nThen we slot in a volume:\n\nNow that we've got everything organized, we can bring in the PDS container itself:\n\nI make this container boot before my Caddy service which brings up all the\nassociated resources as part of the quadlet.\n\nWe then make the appropriate changes to the Caddyfile:\n\nNow I get autoupdates for my PDS without needing to use the watchtower container\nalong with logs that feed right into systemd. Additionally, my PDS storage\nitself ends up abstracted away for me in a podman volume, rather than being\nscattered in a random non-standard place on my VPS. In short, it does basically\nexactly what I want it to do, just the way I want it, with some learnings along\nthe way.\n\n[^1]:\n    I've actually moved this server back over to an Ubuntu 24.04 deployment,\n    due to RHEL-likes running a bit slow for me when it comes to package updates --\n    just kidding, it's back to using CentOS Stream now\n\n[^2]:\n    the oneshot method is a totally valid way of doing it to make it \"easy\",\n    but it had too many quirks / compromises for my liking",
  "title": "Self hosting your PDS with Podman"
}