# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

zrok-cloud is a containerized deployment system for OpenZiti's [zrok](https://github.com/openziti/zrok). It builds Docker containers that consume environment variables and auto-generate YAML configuration files via Jinja2 templates. A single container image supports three execution modes controlled by `ZROK_COMMAND`: `ctrl` (controller), `http` (public HTTP frontend), and `dynamicProxy` (dynamic proxy frontend).

## Build & Run Commands

**Build and push to Docker Hub** (requires Docker Hub credentials, linux/amd64 only):
```bash
./push_new_tag.sh [VERSION]       # VERSION defaults to 'latest', tags as VERSION-GITHASH
```

**Local development build and run:**
```bash
cp set_local_env.sh ${USER}-env.sh  # Copy template, fill in env vars
./run_local.sh [VERSION]            # Builds image and runs container locally
```

**Dev build** (uses `devbuild.Dockerfile`, expects a local `zrok` binary in repo root):
```bash
docker build -f devbuild.Dockerfile -t zrok-cloud:dev . --build-arg IMG_TAG=latest
```

**Build tests:**
```bash
cd tests/
docker build -t local-zrok-tester --platform linux/amd64 . --build-arg ZROK_VERSION=0.4.20
docker run -e ZROK_TOKEN=<token> -e ZROK_VERSION=0.4.20 -v "$(pwd)"/logs:/logs --platform linux/amd64 local-zrok-tester
```
Test output goes to `./logs/runlog.log`. Tests use the `bash_test_tools` framework and require a valid `ZROK_TOKEN`.

**ask-http Go service** (domain validation microservice):
```bash
cd ask-http/
go build -o ask-http .
./ask-http/push_new_tag.sh [VERSION]  # Build and push container
```

## Architecture

### Configuration Generation Pipeline

```
Environment Variables → zrok_cloud_entrypoint.py → Jinja2 Templates → YAML Config → zrok process
```

1. `zrok_cloud_entrypoint.py` reads `ZROK_*` env vars with defaults
2. Builds a config dictionary and renders the appropriate Jinja2 template from `templates/`
3. Validates the rendered output as valid YAML
4. Writes config + identity files to `/home/zrok/`
5. Execs the corresponding zrok subprocess

### Execution Modes (ZROK_COMMAND)

| Mode | Template | zrok Command | Key Env Vars |
|------|----------|-------------|--------------|
| `ctrl` | `ctrl.yml.j2` | `zrok controller config.yml` | ZROK_ADMIN_SECRET, ZROK_STORE_PATH, ZROK_ZITI_* |
| `http` | `http-frontend.yml.j2` | `zrok access public config.yml` | ZROK_ZITI_IDENTITY_JSON, ZROK_HASH_KEY, OAuth vars |
| `dynamicProxy` | `http-frontend-v2.yml.j2` | `zrok access dynamicProxy config.yml` | ZROK_FRONTEND_TOKEN, ZROK_AMQP_URL |

### Key Files

- `zrok_cloud_entrypoint.py` — Main entrypoint; all config generation and process launch logic
- `templates/ctrl.yml.j2` — Controller Jinja2 template (limits, metrics, maintenance, store, ziti)
- `templates/http-frontend.yml.j2` — Public frontend template (v1, OAuth providers via `ZROK_PROVIDERS_JSON`)
- `templates/http-frontend-v2.yml.j2` — Dynamic proxy frontend template (AMQP subscriber, frontend token)
- `Dockerfile` — Production image based on `openziti/zrok2`, runs as `nobody` user
- `devbuild.Dockerfile` — Dev image based on `openziti/zrok`, copies local zrok binary

### Supporting Services

- **ask-http/** — Go (gin) microservice that checks domain availability against the zrok PostgreSQL database. Endpoint: `GET /?domain=example.com`
- **caddy-build/** — Caddy reverse proxy container for TLS termination
- **bootstrap/** — Numbered bash scripts (1-4) for initial environment setup: zrok bootstrap → ctrl bootstrap → frontend creation → dynamic frontend setup

### Container Details

- Base image: `openziti/zrok2:$IMG_TAG` (production) or `openziti/zrok:$IMG_TAG` (dev)
- Python deps: `jinja2`, `PyYAML` (installed via pip at build time)
- Runs as `nobody` user, `HOME=/home/zrok`
- Version tag format: `{ZROK_VERSION}-{GIT_SHORT_HASH}`

## CI/CD

Jenkins pipelines in `jenkinsfiles/` using `nf-jenkins-shared-libraries@master`. Key pipelines:
- `build-zrok-cloud.jenkinsfile` — Builds and pushes Docker image
- `deploy-DEV-build.jenkinsfile` — Deploys to sandbox/staging environments
- `deploy-2.x-build.jenkinsfile` — v2.x specific deployment

## Environment Variables

All env vars use the `ZROK_` prefix. The full reference is in `README.md`. Key conventions:
- Hierarchical naming: `ZROK_{SECTION}_{SUBSECTION}_{KEY}` (e.g., `ZROK_LIMITS_BANDWIDTH_PERIOD`)
- `None` defaults mean the variable is required or conditionally required
- `ZROK_DEBUG=true` enables verbose logging and config file dump
- `ZROK_CMD_FLAGS` passes additional flags to the zrok subprocess
- `ZROK_PROVIDERS_JSON` accepts a JSON array of OAuth provider configs for the frontend templates

## Sensitive Files

User-specific env files (`*-env.sh`), `.checkpoint*`, `*.jwt`, and `*.json` are gitignored. Never commit credentials or identity files.
