$6/mo Agent-Friendly Side Project Stack
2026 Jun 5
See all posts
$6/mo Agent-Friendly Side Project Stack
I recently found myself with some time on my hands, so I built a news filtering service for myself
with Claude. I didn't like scrolling through multiple apps on my phone
or newsletters in my email, subject to the whims of each news source's
algorithm, and the solutions out there charge outrageous subscription
fees like $10/mo to
simply run an LLM query and send an email. Turns out I was not
alone, there are hundreds of similar projects and so probably no one
but me will continue using it. Anyhow, the process got me thinking about
what the minimalist side project setup looks like in this new world of
agentic coding tools. I put some thought into it and it might be useful
to others. My goals generally were:
Host web services including, but not limited to, a blog
Reliably run long periodic/background jobs
Minimize cost
Minimize dependencies
Maximize performance, scalability and reliability
In terms of source control, there were 2 main questions: monorepo or
dedicated and private or public. I wanted to maximize optionality for
each project's future, so a private monorepo made the most sense for
early incubation. If a project gains traction, you can split it out into
a dedicated repo should you want other contributors and choose private
or public depending on what makes sense for the project. A directory per
project in the monorepo is fine for isolation.
For long running background jobs, local launchd services or Claude
Cowork scheduled tasks, while simple, are generally not viable because
they require my laptop to be on. For my news service, I wanted to get a
newsletter on my phone before opening my laptop in the morning. There
are many other reasons to decouple from the laptop: scaling, uptime and
so on. So it is necessary to get an external 24/7 machine. If my goal
was only to run background jobs, then I would have considered
using Github Actions alone because the Github dependency is already
necessary for source control. However, GHA has relatively small caps for
private repos (2k minutes/month, 500MB artifact storage etc.) before you
leave the free tier and there is no way to host web services or domains
through GHA.
The combination of long running background jobs and hosted web
services, while minimizing cost, narrows the options significantly.
There are many services out there which optimize for cheap static site
hosting (Cloudflare Pages, Netlify, Vercel, Github Pages) or web app
hosting (Render, Railway, Heroku), but usually not both, nor with real
support for background tasks. Their margin depends on users wanting to
avoid dealing with their own server and the associated SRE workload:
infra configuration, updates, backups and so on. However, the burden of
such SRE workloads has dropped significantly with agentic coding tools.
Even as a developer who doesn't want to spend a lot of time SREing, I
found that working with infra via Claude/Codex was relatively
straightforward. So I steered away from managed solutions towards raw
infra to minimize costs, taking Claude/Codex cost as a given as it's
simply required to move through the world in 2026.
I briefly looked at running my own hardware at home, but the
electricity costs (especially if you live in a major US metro) are
astronomically more than what cloud vendors can get by setting up their
data centers in a place like Iceland. So it just became a question of
which cloud vendor to use. Cloud vendors fall into 2 main categories.
There are the big 3 hyperscale "everything clouds" - AWS, GCP, Azure -
which can support the most complex workflows and the biggest scale in
the world. Cloudflare increasingly has moved into that space as well
from the edge inward and has a very generous free tier. The other big
category is "indie clouds" like Digital Ocean, OVH and Hetzner. Indie
clouds generally have significantly cheaper raw resources like compute
(Hetzner is around 3-5x cheaper for a simple linux server), but less
managed services. Again the managed services are of significantly less
value in the agentic world, especially with simple side projects that
are not processing gargantuan numbers of users/data like Youtube. With
my joint goals of minimizing cost and maximizing
performance/scalability, I ultimately chose to leverage the generous
free tier of Cloudflare, which covers basically everything at the edge
(global CDN, origin hiding, better DDoS protection) and combine it with
a Hetzner VPS as a cheap source of compute. I did consider something
like Cloudflare workers/queues, with the goal of one less dependency,
but the limitations in the free tier are relatively tight (CPU time per
req 10ms, 128MB memory per isolate etc.) whereas a CAX11 on Hetzner gets
you just unlimited access to 2vCPUs/4GB memory for ~$6/mo. Notably you
can also scale up to the CAX41 at 16vCPUs/32GB memory while still
keeping the same disk (i.e. no data loss) for simply ~$37/mo, which
could likely support an app with 10s of thousands of users. If one of my
random side projects went beyond that scale, I'd have no problem
investing more time in the infra.
To keep infra management AI friendly and well documented, I've always
preferred to manage through IaaC (Terraform or Pulumi). One of the
drawbacks of using an indie cloud to save cost is that the IaaC provider
support of that cloud can sometimes be spotty, but luckily for
Cloudflare and Hetzner the support is sufficient. I purchased a domain
name (cstein.xyz) on Cloudflare and made
an account on Hetzner and created API tokens on both through their UIs.
I set those API tokens as Pulumi secrets, then went ahead and created
DNS records, SSH keys, servers etc. via Pulumi + Claude. Side projects
can simply use subdomains (e.g. distill.cstein.xyz), if they scale then
you purchase a more specific name. The one manual step is setting up
Authenticated Origin Pulls (mTLS between Cloudflare and the Hetzner
server) which involves downloading a keypair from Cloudflare and copying
it to the server. That is important security wise as it prevents people
from bypassing Cloudflare and accessing the Hetzner server directly.
After that step I installed Caddy on the server and used that as a
reverse proxy for all domains:
# Shared TLS snippet for Cloudflare origin pull
(cloudflare_tls) {
tls /etc/caddy/origin.pem /etc/caddy/origin-key.pem {
client_auth {
mode require_and_verify
trusted_ca_cert_file /etc/caddy/cloudflare-origin-pull-ca.pem
}
}
}
# News
distill.cstein.xyz {
import cloudflare_tls
log {
output file /var/log/caddy/news-access.log {
roll_size 10MiB
roll_keep 3
}
format json
}
reverse_proxy localhost:3000
}
With that you can expose any new web service (including a static
blog) publicly on the same server with their own domains as simply new
records in Cloudflare/Caddyfile.
How do you get your code onto the server? Again, for simplicity, I
wanted to keep a single server to start and just host multiple apps on
it. Docker is the obvious standard for deployment because it avoids
installing app specific dependencies on the server (unlike rsync). I
considered just encoding the global dependency set in a cloud-init
script in the server's IaaC representation, but the problem with that is
any changes there result in destroying and recreating the server, wiping
all the data. A big benefit of docker is the incremental deployment
model, but to get that you need a docker registry. I didn't want to add
a new dependency on Docker Hub or some other piece of infra to store the
images, I just want the ability to quickly push an image to the server
securely. The easiest way to do that was to run a docker registry on the
Hetzner server and push images directly to it via SSH port forwarding
(GHA step):
- name: Push image via SSH registry tunnel
run: |
REMOTE="connor@${HETZ_SERVER_IP}"
ssh "$REMOTE" "docker inspect registry >/dev/null 2>&1 || \
docker run -d --restart=always -p 127.0.0.1:5000:5000 --name registry registry:2"
ssh -fNL 5000:127.0.0.1:5000 "$REMOTE"
sleep 2
docker tag "news-digest:${IMAGE_TAG}" "localhost:5000/news-digest:${IMAGE_TAG}"
docker push "localhost:5000/news-digest:${IMAGE_TAG}"
pkill -f "ssh -fNL 5000:127.0.0.1:5000 ${REMOTE}" || true
This is great because it leverages the pre-existing SSH pathway which
you need regardless as a fallback for server debugging, instead of
introducing a new dependency. Per project directory in the monorepo, I
set up a GHA that does the following on commit/merge to master: run
tests, build a docker image tagged with that commit and push that image
to the server over the SSH tunnel. The deploy step can also prune older
images to prevent the disk space from growing indefinitely.
The last piece of the puzzle was secret management. Any service you
run will necessarily need secrets; they need to be stored securely but
also accessible by the service. Hetzner doesn't have a fancy secret
management service like the hyperscale clouds do, but even then most of
the secrets you need in a side project context are API keys for 3rd
party app dependencies (LLMs, Stripe, etc.) which generally are not of
critical security importance. The solution I chose was to use Github
secrets as my secret manager. I grouped secrets per app using Github
environments and then when CI deploys it copies the relevant secrets
into a .env file and uses scp to copy them to the server. This way
everything is protected by my SSH key and Github account, which makes it
easy to reason about the security model.
So with these 3 main dependencies (assuming Claude is a given) -
Github, Cloudflare, Hetzner - you can build basically any side
project/personal automation you want with decent performance, for
~$6/mo. If one starts growing, you can scale up to 10s of thousands of
users for ~$37/mo. For a few more dollars a month you can add automatic
backups or a bigger disk at Hetzner. The one thing you don't necessarily
get out of the box is extreme high availability (HA) or blue/green
deployments, but Hetzner's uptime SLA is 99.9% or 8hr a year which is
completely fine for many, many use cases. If I did really require HA or
blue/green deployments, I would get one additional Hetzner machine and
use Claude to guide me through automatic failover between the 2
machines.
Questions or comments? Email feedback@cstein.xyz
$6/mo Agent-Friendly Side Project Stack
2026 Jun 5 See all postsI recently found myself with some time on my hands, so I built a news filtering service for myself with Claude. I didn't like scrolling through multiple apps on my phone or newsletters in my email, subject to the whims of each news source's algorithm, and the solutions out there charge outrageous subscription fees like $10/mo to simply run an LLM query and send an email. Turns out I was not alone, there are hundreds of similar projects and so probably no one but me will continue using it. Anyhow, the process got me thinking about what the minimalist side project setup looks like in this new world of agentic coding tools. I put some thought into it and it might be useful to others. My goals generally were:
Host web services including, but not limited to, a blog
Reliably run long periodic/background jobs
Minimize cost
Minimize dependencies
Maximize performance, scalability and reliability
In terms of source control, there were 2 main questions: monorepo or dedicated and private or public. I wanted to maximize optionality for each project's future, so a private monorepo made the most sense for early incubation. If a project gains traction, you can split it out into a dedicated repo should you want other contributors and choose private or public depending on what makes sense for the project. A directory per project in the monorepo is fine for isolation.
For long running background jobs, local launchd services or Claude Cowork scheduled tasks, while simple, are generally not viable because they require my laptop to be on. For my news service, I wanted to get a newsletter on my phone before opening my laptop in the morning. There are many other reasons to decouple from the laptop: scaling, uptime and so on. So it is necessary to get an external 24/7 machine. If my goal was only to run background jobs, then I would have considered using Github Actions alone because the Github dependency is already necessary for source control. However, GHA has relatively small caps for private repos (2k minutes/month, 500MB artifact storage etc.) before you leave the free tier and there is no way to host web services or domains through GHA.
The combination of long running background jobs and hosted web services, while minimizing cost, narrows the options significantly. There are many services out there which optimize for cheap static site hosting (Cloudflare Pages, Netlify, Vercel, Github Pages) or web app hosting (Render, Railway, Heroku), but usually not both, nor with real support for background tasks. Their margin depends on users wanting to avoid dealing with their own server and the associated SRE workload: infra configuration, updates, backups and so on. However, the burden of such SRE workloads has dropped significantly with agentic coding tools. Even as a developer who doesn't want to spend a lot of time SREing, I found that working with infra via Claude/Codex was relatively straightforward. So I steered away from managed solutions towards raw infra to minimize costs, taking Claude/Codex cost as a given as it's simply required to move through the world in 2026.
I briefly looked at running my own hardware at home, but the electricity costs (especially if you live in a major US metro) are astronomically more than what cloud vendors can get by setting up their data centers in a place like Iceland. So it just became a question of which cloud vendor to use. Cloud vendors fall into 2 main categories. There are the big 3 hyperscale "everything clouds" - AWS, GCP, Azure - which can support the most complex workflows and the biggest scale in the world. Cloudflare increasingly has moved into that space as well from the edge inward and has a very generous free tier. The other big category is "indie clouds" like Digital Ocean, OVH and Hetzner. Indie clouds generally have significantly cheaper raw resources like compute (Hetzner is around 3-5x cheaper for a simple linux server), but less managed services. Again the managed services are of significantly less value in the agentic world, especially with simple side projects that are not processing gargantuan numbers of users/data like Youtube. With my joint goals of minimizing cost and maximizing performance/scalability, I ultimately chose to leverage the generous free tier of Cloudflare, which covers basically everything at the edge (global CDN, origin hiding, better DDoS protection) and combine it with a Hetzner VPS as a cheap source of compute. I did consider something like Cloudflare workers/queues, with the goal of one less dependency, but the limitations in the free tier are relatively tight (CPU time per req 10ms, 128MB memory per isolate etc.) whereas a CAX11 on Hetzner gets you just unlimited access to 2vCPUs/4GB memory for ~$6/mo. Notably you can also scale up to the CAX41 at 16vCPUs/32GB memory while still keeping the same disk (i.e. no data loss) for simply ~$37/mo, which could likely support an app with 10s of thousands of users. If one of my random side projects went beyond that scale, I'd have no problem investing more time in the infra.
To keep infra management AI friendly and well documented, I've always preferred to manage through IaaC (Terraform or Pulumi). One of the drawbacks of using an indie cloud to save cost is that the IaaC provider support of that cloud can sometimes be spotty, but luckily for Cloudflare and Hetzner the support is sufficient. I purchased a domain name (cstein.xyz) on Cloudflare and made an account on Hetzner and created API tokens on both through their UIs. I set those API tokens as Pulumi secrets, then went ahead and created DNS records, SSH keys, servers etc. via Pulumi + Claude. Side projects can simply use subdomains (e.g. distill.cstein.xyz), if they scale then you purchase a more specific name. The one manual step is setting up Authenticated Origin Pulls (mTLS between Cloudflare and the Hetzner server) which involves downloading a keypair from Cloudflare and copying it to the server. That is important security wise as it prevents people from bypassing Cloudflare and accessing the Hetzner server directly. After that step I installed Caddy on the server and used that as a reverse proxy for all domains:
With that you can expose any new web service (including a static blog) publicly on the same server with their own domains as simply new records in Cloudflare/Caddyfile.
How do you get your code onto the server? Again, for simplicity, I wanted to keep a single server to start and just host multiple apps on it. Docker is the obvious standard for deployment because it avoids installing app specific dependencies on the server (unlike rsync). I considered just encoding the global dependency set in a cloud-init script in the server's IaaC representation, but the problem with that is any changes there result in destroying and recreating the server, wiping all the data. A big benefit of docker is the incremental deployment model, but to get that you need a docker registry. I didn't want to add a new dependency on Docker Hub or some other piece of infra to store the images, I just want the ability to quickly push an image to the server securely. The easiest way to do that was to run a docker registry on the Hetzner server and push images directly to it via SSH port forwarding (GHA step):
This is great because it leverages the pre-existing SSH pathway which you need regardless as a fallback for server debugging, instead of introducing a new dependency. Per project directory in the monorepo, I set up a GHA that does the following on commit/merge to master: run tests, build a docker image tagged with that commit and push that image to the server over the SSH tunnel. The deploy step can also prune older images to prevent the disk space from growing indefinitely.
The last piece of the puzzle was secret management. Any service you run will necessarily need secrets; they need to be stored securely but also accessible by the service. Hetzner doesn't have a fancy secret management service like the hyperscale clouds do, but even then most of the secrets you need in a side project context are API keys for 3rd party app dependencies (LLMs, Stripe, etc.) which generally are not of critical security importance. The solution I chose was to use Github secrets as my secret manager. I grouped secrets per app using Github environments and then when CI deploys it copies the relevant secrets into a .env file and uses scp to copy them to the server. This way everything is protected by my SSH key and Github account, which makes it easy to reason about the security model.
So with these 3 main dependencies (assuming Claude is a given) - Github, Cloudflare, Hetzner - you can build basically any side project/personal automation you want with decent performance, for ~$6/mo. If one starts growing, you can scale up to 10s of thousands of users for ~$37/mo. For a few more dollars a month you can add automatic backups or a bigger disk at Hetzner. The one thing you don't necessarily get out of the box is extreme high availability (HA) or blue/green deployments, but Hetzner's uptime SLA is 99.9% or 8hr a year which is completely fine for many, many use cases. If I did really require HA or blue/green deployments, I would get one additional Hetzner machine and use Claude to guide me through automatic failover between the 2 machines.
Questions or comments? Email feedback@cstein.xyz