Spinning Up Your Own Corner of the ATmosphere

Thanks for subscribing and reading my first blog post! :)

This is a small but slightly more detailed guide for how to deploy a PDS, for official instructions, check here:

GitHub - bluesky-social/pds: Bluesky PDS (Personal Data Server) container image, compose file, and documentation

Bluesky PDS (Personal Data Server) container image, compose file, and documentation - bluesky-social/pds

💡 If you get stuck at any part of this walk through, check the troubleshooting guide at the bottom or contact me on bluesky !

What you'll need before we get started

Domain name (any domain you can add DNS records for)

Basic terminal comfort (running scripts, commands, etc)

Server you have root access, can SSH into, and has a public IPv4 address (try upcloud !)

Spinning up a server

For this guide, we'll be using UpCloud , you may use another provider or even use a homelab setup with a Synology DS723+ or something.

1. Open up UpCloud Hub (or your provider's website)

2. Select deploy a new server, the recommended specs are 1 core, 1GB memory, 20GB storage (this will be suitable for up to 20 users )

3. You'll probably want backups to ensure no data loss, so enable "Automated backups" for whatever frequency you'd like (or try AT Backup if you prefer local backups)

4. For operating system, choose Ubuntu 20.04, 22.04, Debian 11 and Debian 12 (remember only these versions are supported)

5. Make sure you have at least a IPv4 address enabled

6. Go ahead and click that Deploy button!

Connect to your fresh new server

Go ahead and SSH into your new server. If you're unsure how to connect, scroll to the bottom of your UpCloud server's page and click "How to connect".

Allow network requests into your server

In your UpCloud server's page, go to "Firewall" and open up these ports (and enable the firewall if you haven't yet):

80/tcp (Used only for TLS certification verification)

443/tcp (Used for all application requests)

Your firewall rules should look like this:

Make your future PDS accessible on the internet

Add these DNS records:

One A record at the (sub)domain (e.g. example.com) pointing to your server's IP

One wildcard A record for the (sub)domain (e.g. *.example.com) pointing to your server's IP

Both of these should have TTL set to 600

💡 Tip: to obtain your server's IP, enter the "Network" tab and copy the "Public IPv4"

Setup the PDS on your server

Now that all the firewall rules and DNS records are ready, let's setup the PDS on your server.

1. Download the installer script

wget https://raw.githubusercontent.com/bluesky-social/pds/main/installer.sh

2. Run the installer script

sudo bash installer.sh

The installer script will ask you to enter your domain and admin email, and then it will proceed to install docker and the other required packages . It will also create caddy config, ufw firewall rules, symlinks, and the docker container/config.

Check out your new PDS!

Your PDS should now be deployed and accessible from the internet, go ahead and open the PDS's URL in a new tab. You should be greeted with this page:

⚠️ Don't see your site? Your DNS might not be fully propagated yet.

Now, you may think you're done, but if you want to be able to do PLC (identity) operations and verify your email, you'll have to connect a SMTP server. For this guide, we'll use resend.com , but you can use any SMTP server.

💡 Connecting your PDS to a email server is highly recommended but your PDS can still function without one

Connecting your PDS to a SMTP server

First, enter your editor of choice to edit /pds/pds.env

💡 Take note that in this file, it defines the hostname of your PDS, the rotation keys, and admin password (you can use this to make special requests to the PDS as an admin, this is not an account)

Now, let's add the variables so our PDS can send emails:

PDS_EMAIL_SMTP_URL=smtps://resend:<your api key here>@smtp.resend.com:465/
PDS_EMAIL_FROM_ADDRESS=admin@your.domain

Then, restart your PDS:

sudo docker restart pds

Move your existing account(s) to your new PDS

You likely already have an account on another PDS, but don't worry! Migrating to your new PDS is easy with atpairport.com (made 98% by @knotbin.com and 2% me!), open up Airport and sign in to your old account (for this guide, we will be using my project's account ), select "Departures", fill out the information, and for "Invitation Code" head into that terminal and create an account with pdsadmin:

sudo pdsadmin create-invite-code

After you input all the required information, "Proceed to check-in", follow the prompts, and sit back while Airport migrates your account to your new PDS!

💡 Wondering what gets migrated? Everything! DMs are (as of August 2025) centralized and tied to your DID, and all your records (CAR file) and attachments (blobs) and migrated with you!

Prefer to use command line to migrate?

You can use your terminal too to migrate with goat! I haven't personally migrated with via goat, so you'll have to check out @bnewbold.net's handy guide for that !

Migrating PDS Account with `goat` | bryan newbold (🇪🇺🚄)

Account migration is an important feature of atproto, and has been possible in the live network since February of this year, but is still a bit scary and developer-oriented. As part of documenting the migration process, I recently implemented basic account migration in the goat CLI tool for atproto…

Setting a contact email

Consider setting PDS_CONTACT_EMAIL_ADDRESS to your email address so people can contact you if there's something wrong! Add something like this into /pds/pds.env:

# ...
PDS_CONTACT_EMAIL_ADDRESS="example@example.com"

and... restart your PDS:

sudo systemctl restart pds

Troubleshooting

My PDS isn't working

Check your docker logs, they may show why it's not working:

sudo docker logs pds -f

My PDS isn't sending emails

Check your SMTP provider's documentation, or contact their support.

My PDS isn't accessible on the internet

Have you checked your DNS records? They may be incorrect or have not propagated yet.

Check your firewall rules, they may not be allowing your traffic to your PDS.

Restart the PDS: sudo docker restart pds

Having troubles with ATP Airport?

Contact me on Bluesky so we can fix that, or create a issue on Airport's GitHub . We want Airport to be a bug-free experience!

Want a cool custom / route like my PDS ?

Create your custom ASCII art with this handy tool and then:

mkdir -p /pds/caddy/etc/caddy/static
nano /pds/caddy/etc/caddy/static/index.txt # put your content here

tell caddy to serve this file:

nano /pds/caddy/etc/caddy/Caddyfile

and add this in your domains block:

*.pds.pin.to.it, pds.pin.to.it { # keep your own domains here
tls {
on_demand
}

# only add these 2 blocks
@rootPath {
path /
}

handle @rootPath {
root * /etc/caddy/static
file_server {
index index.txt
}
header Content-Type text/plain
}

reverse_proxy http://localhost:3000
}

and... restart your PDS to reflect these changes

sudo systemctl restart pds

Your PDS should now have your new start page! ✨ Check out mine here:

pds.pin.to.it