Running my own infrastructure

Hi, I'm Reese Wells
I build and maintain self-hosted systems

A systems-focused developer passionate about self-hosting, infrastructure automation, and building reliable services that just work. From container orchestration to local AI, I manage a full homelab stack from DNS to deployment.

Reese Wells

Infrastructure, automation, and self-hosting

I'm a systems developer who thrives on building and maintaining self-hosted infrastructure. My work spans the full stack of homelab operations: from OS image building with osbuild and Ansible-driven deployments, to container orchestration with Podman quadlets and Kubernetes, to local AI inference and observability.

I maintain two main repositories: one for documentation, notes, and tutorials on self-hosted services, and another for the automation layer that deploys and manages services across a fleet of servers. Every service runs as a rootless container with dedicated systemd user sessions, backed by centralized BorgBackup.

80+
Services
2
Domains
100%
Self-Hosted

What I work with

A broad toolkit focused on infrastructure, automation, and self-hosted services.

Container Orchestration

Rootless containers managed via Podman quadlets, Docker Compose, and Kubernetes clusters with Helm charts.

Podman Docker Kubernetes k3s

Infrastructure Automation

Ansible playbooks drive deployments across a multi-server fleet with strict SOP ordering and centralized configuration.

Ansible osbuild systemd BorgBackup

Networking & DNS

AWS Route53 powers all DNS management with DDNS auto-updating, Caddy reverse proxy with Route53 DNS-validated TLS, and dual-domain strategy.

Route53 Caddy Nginx WireGuard
🤖

Local AI & ML

Full local AI stack: Ollama, LiteLLM, LocalAI for inference, Langfuse for observability, with CUDA and ROCm support.

Ollama LocalAI Langfuse ROCm

Python

Python is the backbone of the homelab: DDNS updates, fleet-wide deployment scripts, AWS integration, and automation tooling with boto3, rich, and uv.

Python boto3 uv mypy

Featured Projects

What I've built

A selection of projects from my homelab and deployment infrastructure.

version: '3.8'
services:
  caddy:
    image: caddy:2-alpine
    networks:
      - default
    labels:
      - "caddy.*.reeseapps.com"

Reverse Proxy Infrastructure

Caddy and Nginx reverse proxies serving all *.reeseapps.com domains with AWS Route53 DNS-validated TLS. DDNS auto-updates IPv4/IPv6 records across the fleet.

Caddy Nginx Route53 Podman
def update_record(domain):
  ipv4 = get_public_ip()
  record = route53.find(domain)
  if record.value != ipv4:
    route53.update(record, ipv4)
    log(f"Updated {domain}")
 
# Run every 5 minutes

Dynamic DNS Service

Automated DDNS keeping AWS Route53 records updated for all servers. Manages dual-domain strategy: reeseapps.com for public services and reeselink.com for internal machine-to-machine connections.

Python AWS CLI Route53 Podman
from ollama import Client
 
client = Client("http://localhost:11434")
response = client.chat(
  model="llama3",
  messages=[...]
)
 
# LiteLLM proxy for unified API

Local AI Stack

Complete local AI infrastructure: Ollama and LocalAI for inference, LiteLLM as a unified API proxy, Bifrost for model routing, and Langfuse for observability. Supports both CUDA and ROCm.

Ollama LocalAI LiteLLM Langfuse
# Ansible playbook
- name: Deploy Gitea
  hosts: gitea
  tasks:
  - docker_compose_v2:
    project_src: /opt/gitea
    state: present

Deployment Automation

Ansible-driven deployment pipeline with strict SOP ordering (osbuild -> ddns -> caddy -> nginx -> ntfy -> gitea). Each service runs as a rootless container with dedicated systemd user sessions and centralized BorgBackup.

Ansible Podman systemd Borg
# Self-hosted services
- Immich # Photo/video management
- Jellyfin # Media streaming
- Nextcloud # Cloud storage & sync
- Gitea # Git service
- Matrix # Chat protocol
- Home Assistant # Smart home
- Pi-hole # DNS ad blocking

Self-Hosted Services

A diverse fleet of self-hosted services: Immich for photos, Jellyfin for media, Nextcloud for storage, Matrix for chat, Home Assistant for IoT, and more. Each running as rootless Podman containers with SELinux awareness.

Immich Jellyfin Nextcloud Matrix
# Kubernetes with k3s
- metallb # L2 load balancer
- longhorn # Distributed storage
- traefik # Ingress gateway
- external-dns # Route53 integration
- grafana # Metrics dashboards
- minecraft # Game server

Kubernetes Cluster

k3s and k0s Kubernetes clusters with MetalLB for L2 failover, Longhorn for distributed storage, Traefik/Nginx ingress, cert-manager with Route53 DNS challenge, and Helm charts for service deployment.

k3s Kubernetes Helm MetalLB

Get In Touch

Let's connect

Always open to discussing self-hosting, infrastructure, open source, or just sharing homelab stories.

Trust

Public GPG Keys

Use these keys to verify signed commits and communications. Both keys belong to Reese Wells.

🔒

Primary Key

reese.wells@ducoterra.net

Fingerprint: 7FC1 B297 0011 4F4F C589 E706 5FDD CFA5 44D7 7B8C
-----BEGIN PGP PUBLIC KEY BLOCK-----

mDMEaE5XjhYJKwYBBAHaRw8BAQdAURfgqa4xpT9tTtRETfknsq8UacTcUeXd2P+N
CmdSxw+0IVJlZXNlIFdlbGxzIDxyZWVzZUBkdWNvdGVycmEubmV0PoiPBBMWCAA3
BAsJCAcCFQgCFgECGQECngECmwMWIQR/wbKXABFPT8WJ5wZf3c+lRNd7jAUCaOe5
HQUJBHjscgAKCRBf3c+lRNd7jDo+AP9ElEJP3nsUcW9TbStKwmu0Iq5cjwbDofYx
aoo8lxpgYAEAtEnBYpRz8g94NpCi0TF2EGCmlQupJy1S0nlQdkW3QQq0IVJlZXNl
IFdlbGxzIDxkdWNvdGVycmFAZ21haWwuY29tPoiPBBMWCAA3BAsJCAcCFQgCFgEC
GQACngECmwMWIQR/wbKXABFPT8WJ5wZf3c+lRNd7jAUCaOe5HQUJBHjscgAKCRBf
3c+lRNd7jMoiAP4scAB+6RdRTIo/UvLzI5LdO0Ej1W9i6d09Vmt5T3ES3wD/e2JD
CNwMixU02xbSh0wRFwOmBK1ltw3qoABUIoG4Qgu0H1JlZXNlIFdlbGxzIDxkdWNv
d2FlQGdtYWlsLmNvbT6IjwQTFggANwQLCQgHAhUIAhYBAhkAAp4BApsDFiEEf8Gy
lwART0/FiecGX93PpUTXe4wFAmjnuR0FCQR47HIACgkQX93PpUTXe4w/bgEAgr5K
MJypCb1dmjUmFBBLmvEVT7zt8llZbcsrPqQHZo4BAM2lnEa4pQQ5AZ6XMSlx2dSi
V89/RIugpbqhStR+hGsJtCdSZWVzZSBXZWxscyA8cmVlc2Uud2VsbHNAZHVjb3Rl
cnJhLm5ldD6ImQQTFgoAQRYhBH/BspcAEU9PxYnnBl/dz6VE13uMBQJp36cbAhsD
BQkEeOxyBQsJCAcCAiICBhUKCQgLAgQWAgMBAh4HAheAAAoJEF/dz6VE13uMGwUB
AMZTs+ggIGdyDNNHQKxCjSiFj1tV4txdGMhFs7zg061JAQDsnuEZxZ2r5oM+Hl4e
1JmPiUT7TI3I0KyLzSnrE5TiBbg4BGhOV44SCisGAQQBl1UBBQEBB0DwrTk+obNw
CZVjUW/wi97DI7d1VtebvszT24X04nFSawMBCAeIeAQYFggACQWCaE5XjgKbDAAh
CRBf3c+lRNd7jBYhBH/BspcAEU9PxYnnBl/dz6VE13uM79kA/iGOP6Duiw19F/TT
bIbyO3rh99O5VMtxdgYAxhxLF29gAP9p8UwxP0vhCXrB+VrT3p8ZVNtXYswCsXKY
RZXs6UjJArkCDQRoTleOARAAs92LnhZYtwJvOFFVivXb8ZsgHf6oVdK6/c1htn9K
90hbVbVoArMjrHY+3msoZ0sOBd1s1K3/Q9B0lwDJV6VgEggckIxYc6hpoVu9HmiG
XGdIPzbnnyOeV7NHdYpARPBjXt8HKL96O181qS02WhjIg3sDg3pnuCxJ78nOcNvP
F3ANNpPKr05IWme5NAN+kfKrRaurKP3OePHG6l8ZUWGJPxW+jfE2w1R5hGpEqeu6
RgnfaeBGta10tdJE68+i9RLO1KVDgrIC2c+hNzwMPEMgiiM+MHWgC5uHxpWohv+L
cF4STKLYx8uo9VpwuwNXIh6QEqUm/YWQxcrmrvh4+UNupX00zrzgcUCjJxmyChj8
tyYiM6ltqQ2qOjWLdXZfNbdq0vQw7K1jCMg+kESdFF4jGYGBsYqDBrJXvC0fIJF3
oQIcIc+wGP3kikoj1DREpz53loowMWtSaKx1eZky08PT6KSgM3jefLctfmcpCATL
AKW0FksC9xk6U/UatWwSEZ30ZjOOf2yhnnb1tI0g6EvP3528T4dZiyIWPDwegQZv
Bu2Fa+YcAj5cJ3jLO8UoPtXJA1/3KiIWIXKlchBQtAelvbdikMpJCdl3Yzpx4rJ7
A4Oaz7E0eVKR4ZrU62ti1jM9dMNA5AyTiGxZeBAVXc6CNqZUXyFqLQF7T1zuKWEu
baUAEQEAAYkClwQYFggACQWCaE5XjgKbDgJACRBf3c+lRNd7jMFdoAQZAQgABgUC
aE5XjgAKCRCfMr6uYxJ0la7ED/9/wj2h4ntIynkpU2dLeSuibTRKT4o7EMt2P1wt
7oCvTG4n4CGQy/bRMBqK6nWjRAfyDNyJfXq15lWESEzyvKRHeVjzgBQ3uvmk3485
CYO17aIHfci6NMN2LUD8F5WVsNkP6pxuL/RF4tIfxLWb0hNOVREbxLsFrFcvMpl9
9e3zGEQT8nIo/K25Ex9a3SbPW4zStYvVmg3OI44q85hIMrxyw1OZgzV1aLCYAPGf
Brj941Mm0BEdXO28LulJF5eMqdPSNpzF+VPbkz4A3RcbQ+IC09W8YU3+vRjOshkV
++nrd8GEYzlUWL7osz5JCvtUtvCAEBoGfHcqc328vvurHwvHsACysJ/BPPVPnxs/
NfaFybr9f9wqO/4DA+157kAxNWDyQN3v6bIry0e4H1SijBTosgP/QFVW8Te6A7Xc
k4B+r/buFOi4xZEYcS7Sj1g+xhmHWnr9ogWS9NgVJMxgiaFivB9XqLDD6pRKisfR
ukqAKaHjXtA4HLfLOV95plJoEG9KBWeLGOC2MSrytwplOHZGjyf6eWT3T60fplpW
ZKg97p/WBLy2JsKSBLvAgYOAdSp2lbg+BUEMQR4Ik/yC0MLvrV4+534+Vt+KW1cB
QCW6h0ehT137OR4a79Z94nOA3jdvoI8G5svpsXILXxnnRTaNQBm1bh7706NGszqC
lniyJxYhBH/BspcAEU9PxYnnBl/dz6VE13uMFw4A/0G+/1lmIe06f8wk84ajyrjv
pONgYKHcXyh0UkEKz1ufAQDKmC4MEH0My+HFiCmbgYlaZrL1kCAkhSk6SQ1D0k7S
BQ==
=U3eP
-----END PGP PUBLIC KEY BLOCK-----
🔒

Git Signing Key

git@ducoterra.net

Fingerprint: 2FF3 619F A6CA 2A4C FA2D 3532 816E 5FE7 8271 602B
-----BEGIN PGP PUBLIC KEY BLOCK-----

mDMEaPWJEBYJKwYBBAHaRw8BAQdAkbMCw8vlCTSyvxCnaWvFwvvlm7wW94Fgsj47
3NeMC9a0MVJlZXNlIFdlbGxzIChHaXQgU2lnbmluZyBLZXkpIDxnaXRAZHVjb3Rl
cnJhLm5ldD6ImQQTFgoAQQIbAwULCQgHAgIiAgYVCgkICwIEFgIDAQIeBwIXgBYh
BC/zYZ+myipM+i01MoFuX+eCcWArBQJo9l/LBQkDwz27AAoJEIFuX+eCcWArk3cB
AMtkMa5nxG16CaiKMyOGmzlhCZJnS2wvz84DEAMr2BKRAP9Xg//BEVaDMzvRXuU+
Nya5ewmhjfvI0O3dxUfhUIDUCYh1BBAWCgAdFiEEf8GylwART0/FiecGX93PpUTX
e4wFAmj2qewACgkQX93PpUTXe4zbuQD+NiQ8+ubTNSIxoq5qv20rTEIJZwhWamyS
KSCxUnramK0A/Ajzne+dP6ZJh3O96YaTxhQtCibcSqo66/hVndXymvIKiJMEExYK
ADsWIQQv82GfpsoqTPotNTKBbl/ngnFgKwUCaPWJEAIbAwULCQgHAgIiAgYVCgkI
CwIEFgIDAQIeBwIXgAAKCRCBbl/ngnFgK9bsAP47Fth3baT2awbVmlwPEXt17aFI
yIgxXyp9/5DA2QB4QAD/Wy4h8NiWzCzfO6kD1YzgIepVv2UlRH0sQ70vEi5RWAq4
OARo9YkQEgorBgEEAZdVAQUBAQdAeODe7hrNZC143n0+CvNh6x0E9QxGRJfjJPN1
WAV5bWsDAQgHiHgEGBYKACAWIQQv82GfpsoqTPotNTKBbl/ngnFgKwUCaPWJEAIb
DAAKCRCBbl/ngnFgK7kQAQDOnSYe0XO4Hw7QAAo2VhOUHvOjj4c2WSlLuIkyG4n2
XwEAnes79w4eYeMUjIytQWACEvy4QoO7X2MLTKliSqc4Ag8=
=9aAm
-----END PGP PUBLIC KEY BLOCK-----