Using OpenAI Codex in a homelab workflow

Using OpenAI Codex in a homelab workflow

I use OpenAI Codex when I need to get through scripts, infra code, or small automation jobs without spending all evening on the mechanical parts. It is useful, but only if I treat the output as untrusted until I have checked it.

What Codex is

OpenAI Codex turns plain instructions into code. I use it like a smarter autocomplete for functions, small scripts, and config files. It is not perfect, so I read the output, run tests, and check security before I use anything it has produced.

Setting up the environment

  1. Get an API key from OpenAI and keep it in a homelab vault or a local secrets file. When I am testing, I export it into the session:
export OPENAI_API_KEY="sk-..."
  1. Create a clean Python virtualenv for the tooling:
python3 -m venv ~/venvs/codex
source ~/venvs/codex/bin/activate
pip install openai requests
  1. Add a small wrapper script for quick prompt calls. I use something like this, saved as codex-gen.py:
import os, openai, sys
openai.api_key = os.getenv("OPENAI_API_KEY")
prompt = sys.stdin.read()
resp = openai.Completion.create(engine="code-davinci-002", prompt=prompt, max_tokens=400, temperature=0.2)
print(resp.choices[0].text)
  1. Test it with a safe local prompt:
echo "Write a Bash script that installs nginx on Ubuntu 22.04 and creates a systemd service" | python codex-gen.py

I keep API keys off public machines. In practice, that means one jump box and nothing else.

Using it in an IDE

Pick the method that fits your workflow:

  • Use an extension that proxies calls to the OpenAI API and reads OPENAI_API_KEY from the environment.
  • In VS Code, I use a snippet that runs a local script to generate code and paste it into the open editor. That keeps third-party cloud proxies out of the way.
  • If I am using code-server on a homelab VM, I run the API calls from that VM so the generated code stays inside the local network unless I allow it out.

If latency gets in the way, I lower max_tokens and reduce temperature.

Starting with small jobs

I start with repeatable tasks, not broad requests.

  1. Create a prompt template with the goal, constraints, language, and test cases. For example:
  • Goal: generate an Ansible task to install nginx and enable the service.
  • Constraints: idempotent, use apt, target Ubuntu 22.04.
  • Tests: should create a backup of /etc/nginx/nginx.conf.
  1. Ask for one task at a time.
  2. Run linters and unit tests where I can. For shell scripts, that means shellcheck. For Python, I use flake8 and pytest.
  3. If the output fails, I tighten the prompt. Small changes work better than rewriting the whole thing.

Using Codex without handing it the keys to the lab

Breaking multi-step work apart

Codex handles multi-step work better when I split it into chunks. I build a chain of prompts rather than throwing everything into one request.

  • Step 1: ask for a short outline of the steps needed for the feature.
  • Step 2: ask for one artefact at a time, such as a small script, a systemd unit, or an Ansible task.
  • Step 3: run each artefact in isolation and collect the logs.

For example, if I am provisioning a containerised web app, I split it up:

  1. Ask for a Dockerfile that runs a Flask app with uWSGI.
  2. Ask for a docker-compose.yml that exposes port 8000 and mounts a local volume.
  3. Ask for a systemd service that runs docker-compose up in a specific directory.

I run each piece in a disposable VM, check for failures, then combine them.

Using coding agents properly

I treat agents as assistants. They need guardrails and checks.

  • Give them unit tests or smoke tests with the prompt.
  • Ask for file contents only, plus the command to run the tests.
  • Use a low temperature if I want repeatable output.
  • Ask for error handling, logging, and exit codes up front.

One prompt pattern I keep using is:

  • Write a Python 3.11 script that performs X. Include logging to /var/log/x.log, exit codes 0/1, and a simple pytest test file.

I version-control every generated file. That makes rollbacks easy and gives me a clean diff of what the agent changed.

Watching performance

I track three things:

  • Tokens per request. I keep them down for small changes.
  • Failure rate. I look at how often generated files fail linters or tests.
  • Latency. Slow responses break the flow.

I log API usage and responses, then store the usage data in a CSV. If costs or token use start creeping up, I shorten the prompts or only use the model for scaffolding while I write the important logic by hand.

Security checks

Generated code can still be sloppy, and sometimes it is just wrong in ways that matter.

  • Never put secrets in prompts. Use placeholders.
  • Run generated binaries and scripts in isolated sandboxes or VMs first.
  • Check for hardcoded credentials, dangerous exec calls, and unattended remote access.
  • Keep mandatory code review for anything that touches production-facing systems.

On my homelab, I keep agents off the network segments that hold secrets. I also use ephemeral VMs for the first pass.

What it is useful for

  1. Ansible task generator. I give Codex a short inventory description and ask for a minimal, idempotent playbook to install Prometheus node exporter. I run it in a disposable VM and fix the handlers it missed.
  2. CI pipeline templates. I ask for a GitHub Actions workflow that runs tests and builds a Docker image. I add secrets and image push steps by hand.
  3. Refactor help. I paste a function and ask for smaller functions, docstrings, and a test file. It saves time on the mechanical parts while I check the design.

I keep a small repo of prompts that worked well. I tag them by task type and reuse them when they still fit.

  • Start small and use Codex for scaffolding and repetitive work, not final security-sensitive logic.
  • Generate one artefact at a time and check each one.
  • Log usage and failures so you can see tokens, latency, and test pass rates.
  • Protect secrets and run generated code in sandboxes before it goes anywhere useful.
Tags:

Related posts

Monitoring radio, transport and core faults

Private 5G resilience does not come from a cheerful dashboard or a nice radio map. I want to see where the attach failed, which path dropped, and whether the core is quietly spoiling the whole thing;...

Immich | v3.2.2

Immich v3 2 2: small patch fixes cross user face reassign bug, skips faces owned by other accounts, recommended update for users relying on face reassign

Nextcloud | v35.0.0

Nextcloud v35: polished UI, Files and sharing upgrades, better client parity, security hardening, performance and admin gains, developer notes and upgrade tips