Agent evaluation

Task 03

Infra management

The brief

Task 03 — Infrastructure management: harden a small deployment

Review and improve the supplied Dockerfile, compose.yaml, and nginx.conf for a small Python API behind nginx with Postgres and Redis. Do not add Kubernetes or unrelated services.

Goals:

  • No embedded credentials or public database/cache ports.
  • The API runs as a non-root user with a production server and reproducible dependency installation.
  • Add meaningful health checks and startup dependencies based on health.
  • Persist Postgres data, make internal service communication explicit, and add sensible restart/logging/resource settings without pretending Compose is a full orchestrator.
  • Proxy headers and timeouts should be appropriate for a JSON API.
  • Keep local operation straightforward through .env.example.

Deliver corrected configuration and a concise RUNBOOK.md covering startup, health verification, backup/restore, secret handling, and rollback. Write RESPONSE.md listing the highest-risk original problems and verification you performed. Work only in this directory; do not actually start containers.

Inputs given: .env.example, compose.yaml, Dockerfile, nginx.conf, requirements.txt

Scores

Criterion (max)GPT-6 AstraSonnet 5.5Fable 5.1GPT-6.1 SolOpus 5.5Grok 4.7mimoMiniMax M3.1 FlashmuseGPT-6 LunaMiniMax M3
security/correctness (4)3.753.753.53.253.253.25332.52.51.75
operability (3)2.752.752.52.52.52.52.2521.751.751
runbook and judgment (3)2.752.52.52.752.52.251.751.751.51.250.75
Total (10)9.2598.58.58.25876.755.755.53.5
Grader's notes

Letters in the grader's text: A = Sonnet 5.5, B = GPT-6 Astra, C = mimo, D = muse, E = Grok 4.7, F = Opus 5.5, G = MiniMax M3, H = MiniMax M3.1 Flash, I = GPT-6.1 Sol, J = GPT-6 Luna, K = Fable 5.1.

B and A are close; B edges ahead on self-consistency (real readiness probes, transitive pins, tests). I, K and F are near-ties at 8.25-8.5. I is ranked above K for its stronger runbook, despite the likely nginx temp-path startup failure, which was judged statically without running nginx -t. Seven submissions (C, D, E, F, G, H, J) ship placeholder passwords that pass their :? guards; A, B, I and K leave them blank so they fail closed. No containers were started; docker compose config was run on copies with dummy passwords, and all eleven render.

Evaluation 9.25 / 10 graded blind as submission B

The most complete and self-consistent submission. It adds a minimal app with real readiness checks (authenticated SELECT 1 and Redis PING) and pins every transitive dependency, installing with --no-deps and pip check. nginx runs non-root with every temp path moved to tmpfs and upstream resolve. The runbook is accurate and the rollback cannot silently rebuild. Its verification includes passing unit tests and is reported honestly.

Strengths

  • Full transitive pin set installed with --only-binary --no-deps and pip check
  • Non-root nginx (user 101, port 8080, read_only) with all five *_temp_path settings on /tmp; upstream 'server api:5000 resolve' with a zone (valid on nginx 1.28)
  • Authenticated health checks for db (psql over TCP) and cache; api readiness gates the proxy; proxy health check runs end to end
  • Fail-closed blank passwords; Redis has requirepass, LRU and no persistence; internal backend network
  • Runbook: PGPASSWORD inside the container, a .partial temp file for dumps, transactional restore, rollback with --no-build --pull never, accurate Postgres rotation

Weaknesses

  • The allowlist .dockerignore and the COPY of app.py only mean a real multi-module app needs Dockerfile edits
  • Redis password visible in argv via sh -c
  • Adding a stand-in app goes slightly beyond scope (though it is justified)
Evidence the grader checked
  • requirements.txt:6-13 pins blinker, click, Werkzeug and the rest; Dockerfile:15 runs pip install --only-binary=:all: --no-deps && pip check
  • nginx.conf:12-16 temp paths; nginx.conf:27-31 upstream with resolve
  • RUNBOOK.md:89-92 pg_dump with PGPASSWORD and a .partial file; RUNBOOK.md:152 up -d --no-build --pull never --wait
  • RESPONSE.md:53-56 reports 10 unit tests passing and says they are not integration tests

Objective checks

Files

gpt-6-astra/03-infra-management/RESPONSE.md

Infrastructure hardening response

All requested deliverables are complete: corrected Dockerfile, Compose and nginx configuration, .env.example, and RUNBOOK.md. Supporting files include the complete version-pinned Python dependency set, build/source-control exclusions, a minimal API with health endpoints, its HTTP probe, and offline unit tests. The original directory had no application source, so the small JSON API makes the deployment entry point and health checks concrete without adding services.

Highest-risk original problems

  1. Exposed services and embedded credentials. Postgres, Redis, and the API published host ports on all interfaces; Postgres used a literal weak password and Redis had no authentication. Only nginx now publishes a loopback port. Required external passwords, Redis authentication, separate networks, and an internal backend network reduce access. .env and backups cannot enter the allowlisted build context.
  2. Root development server and drifting dependencies. The image ran Flask's development server as root and installed unpinned packages while ignoring requirements.txt. It now runs Gunicorn as UID/GID 10001, installs all eleven runtime packages at exact versions, uses binary wheels without dependency resolution, and checks dependency consistency during the build. Image tags include patch versions. Tags and unhashed wheels are not immutable artifacts; the runbook documents release digests/hashes and the offline advisory limit.
  3. Data durability and upgrade risk. Postgres had no declared reusable data volume and used latest, permitting unplanned major-version changes. It now uses a named volume and a fixed major/patch tag. The runbook includes logical backup, transactional restore, retained-image rollback, and schema/version compatibility precautions. Redis is explicitly disposable cache storage.
  4. Startup races and invisible dependency failures. depends_on only ordered container starts; no service checked readiness. Authenticated database/cache checks gate API startup, and API readiness gates nginx. API readiness tests both dependencies; proxy health tests the full HTTP path. Liveness remains independent of database/cache availability.
  5. Unbounded operation and incomplete proxy behavior. There were no restart, log-rotation, or resource settings; nginx omitted client/proxy headers and explicit API timeouts. These are now configured, with read-only filesystems and dropped capabilities where compatible. Nginx overwrites incoming identity headers, limits request bodies, and refreshes API addresses through Docker DNS. The runbook explicitly describes Compose's health/recovery limitations.

Verification performed

  • Docker Compose v5.1.4 accepted config --quiet with nonsecret test passwords. Inspected/asserted the rendered JSON: exactly four services, only loopback nginx ingress, no API/database/cache host ports, intended network memberships, service_healthy dependencies, persistent database volume, read-only nginx mount, all health checks, restart policies, CPU/memory/PID limits, and log bounds.
  • Verified configuration fails with either password missing and with the unedited .env.example. Verified reserved-character passwords survive rendering, accounting for Compose's literal-dollar escaping. No real credentials were generated or stored.
  • python3 -B -W error::ResourceWarning -m unittest -v test_health.py: 10 tests passed, covering success, dependency/query failure, unexpected replies, missing configuration, connection cleanup, independent liveness, HTTP status/payload checks, malformed JSON, and timeout/connection errors. Third-party libraries are dependency doubles; these are unit behavior checks, not Flask, PostgreSQL, Redis, or container integration tests.
  • Compiled every Python file without writing bytecode. Checked all eleven package entries have exact, unique pins and inspected the Dockerfile's non-root Gunicorn entry point and installation safeguards.
  • Parsed the container shell commands and all six runbook shell blocks using /bin/sh -n without executing them. Reviewed nginx's non-root writable paths, upstream DNS resolution, headers, body limit, and timeout settings statically.

No network requests, image pulls, builds, or container starts were performed. The local environment has no nginx executable or installed application packages; nginx -t, an actual dependency installation/pip check, real health checks, backup/restore, and rollback remain deployment-time verification steps documented in the runbook. Image availability, wheel availability on each architecture, and current security advisories were not verified offline.