Droplet Superpowers

Agent IO June 11, 2025
Source
What's a Droplet? Taken literally, a droplet is a small drop of liquid. Thanks to DigitalOcean , it's now also a clever joke about cloud computing that I only recently got. Here we're running with this new definition: a droplet is a Linux-based virtual machine offered by DigitalOcean . For background, see this nice overview by Adarsh Sojitra . Generally, this discussion will apply to any Linux-based virtual machine where you might use IO, but we'll stick with DigitalOcean for this example because it offers an affordable, easy-to-use service that just might be the least scary way to get started in the cloud. Why use IO? Recalling our discussion of homelabs , IO can provide capability, safety, and convenience for your droplet. Capability. You want to run one or more services and make them publicly available on the internet. These can be websites or APIs that work over HTTP or HTTPS (this includes gRPC). Safety. You want to use HTTPS to connect to your services. You want to require authentication for some or all of your services. You want to be able to block bad traffic to your services. Convenience. You want to be able to easily configure and manage your services. You want to observe the traffic to and from your services. Create a droplet We'll use the smallest size droplet for this example. When you're creating your droplet, add an SSH public key and take a minute to pick a custom name (the defaults are hard to remember). I'm picking names from the NATO phonetic alphabet; this one is "mike". Once your droplet is created, you'll see an option to add a reserved IP address. There's no cost for this , so it's worth doing. With a reserved IP address, you can easily reassign your address to another droplet if you decide to change your backend instance. Configure your domain You should have a domain that you can point at your droplet. Ideally, the DNS for your domain would be configured with two DNS "A" records. The first one (below) routes your root domain to your droplet, and the second routes all subdomains to your droplet. Set these records to your reserved IP address. For these examples, I'm using the domain "noted.at". When your domain records have propagated, you should be able to connect to your droplet with SSH: Create a firewall This is very important! IO creates a bunch of ports that your internal services will use. It also listens on three ports that should be open to the outside world (80, 443, and 2200). You should configure your droplet firewall to ONLY allow access to these ports: 80 and 443 to allow HTTP and HTTPS access 2200 to allow remote SSH connections to your IO and 22 to allow remote SSH connections to your machine Note that you could leave ports 22 and 2200 closed if you install a VPN like Tailscale in your droplet (but we won't in this discussion). Here's the firewall configuration that I'm using: Install Docker First let's install Docker. Use SSH to sign into your droplet and save this as DOCKER.sh : Now run it: When it finishes, you can verify your docker installation with docker info . Here's what I got: Install Nomad Now let's install Nomad. Save the following to a file named NOMAD.sh : Now run it: When that finishes, you can confirm that nomad was installed by running nomad with no arguments: Configure Nomad We need to configure Nomad before we start it. We're going to configure a very simple cluster: just one node that's both a Nomad client and server (you can look up those definitions later). Replace the /etc/nomad.d/nomad.hcl in your droplet with this: This configuration creates some storage for IO in what Nomad calls a "host volume". For this to work, you'll need to also create this directory on your droplet. Start Nomad Now you can start Nomad. Do that by running the systemctl enable subcommand on your droplet, which will cause Nomad to restart whenever your droplet reboots. Here we add the --now option to also start Nomad now. If that worked, you can now run nomad agent-info to get details about your running cluster. Run IO with Nomad Our next step is to set up an an IO that will manage this droplet's HTTP and HTTPS connections. We're going to run this IO with Nomad. Before starting it, you'll need to have an io.db in /srv/nomad/io that is initialized with your license key and SSH users. You can create the io.db by running IO locally. Here license.hcl contains your license key and users.hcl contains the user configuration (see Add an SSH key to allow remote login for an example of users.hcl ). When that's done, copy your io.db to the /srv/nomad/io directory on your droplet Now we need to tell Nomad to run IO. We do that with a Nomad job description that is also represented in HCL (both IO and Nomad use HCL for configuration). Here's the Nomad job description that we need to run IO. Save it in a file named io.hcl and copy it to your droplet. Now, on your droplet, use nomad job run to start your job. If all goes well, you'll be able to see your IO running in Docker. Connect to IO With an IO up and running on your droplet, you should now be able to connect remotely to it. Try this on your local machine (one where your SSH private key is installed): ssh -p 2200 noted.at If all goes well, you'll see the IO console: Create your first ingress Now for fun, let's set up a service on your droplet and give it an IO ingress. From the IO home screen, press i to go to the ingress screen and press n to create a new ingress. Set the host to your droplet's domain. The name can be any user-friendly name, and the backend should be internal:httpbin . This tells your ingress to serve a version of HTTPBin that is built into IO for testing. When that's saved, you should see a view of your ingress like this: We need an SSL certificate for this ingress. Before we can request one, we need to set a contact email address for LetsEncrypt. Go up a level (press ESC ) to the ingress overview screen and press e to edit your general ingress configuration. Tab down to the LetsEncrypt User field and enter your email address. Press tab again and then enter to save this. Now go back to the detail view of your new ingress and press f to "fetch" a certificate from LetsEncrypt. You'll see challenge requests appearing in the traffic screen. After a minute or so, you'll see a message at the bottom confirming that your certificate was generated. Now grab your web browser and visit your droplet domain. You should get the go-httpbin main screen. Congratulations! You now have droplet-publishing superpowers ! Securely connect to your Nomad console with IO For one more trick, we're going to use IO to set up a secure ingress to your Nomad console. Here's the IO configuration: The first block declares a serving interface that points to your droplet's Nomad console and republishes it on port 9009. It also adds an authorization requirement: only AT Protocol users with handles in this handles list will be allowed to connect. Change this to include your handle (and take mine out of it !). The next block declares an ingress for the specified host. Here you should replace nomad.noted.at with some subdomain of your droplet's domain. This ingress includes a block that tells IO to handle AT Protocol signin for this host. The name field will be used in the client id. We only need the atproto scope because we are just asking for a user's identity. Save the modified version of this file on your local system (yes, really) as nomad.hcl and then copy it to your IO with SCP. (Cool, huh? You just uploaded a new configuration using SCP.) Go back to the IO console and get an SSL certificate for your new host. After that, when you try to connect to your new subdomain, you'll be redirected to an AT Protocol signin screen. When you type in your handle and press enter, you'll be redirected to your PDS to sign in. From there you'll go to an authorization screen. If you approve that, you'll be redirected back to your backend, which now is your droplet's Nomad console. To sign out, just visit the /@/signout path of your console host. This and other special AT Protocol authorization features will be the topic of a future post ! Find these files on GitHub

Discussion in the ATmosphere

Loading comments...