aonohako is a Go service for compiling and executing judge submissions over
SSE. It is designed for online judge pipelines that want a small control plane
binary, configurable runtime images, and testable build metadata.
POST /compile,POST /execute,GET /livez, andGET /readyz- queue-controlled SSE responses with
progress,log,image,error, and finalresultevents - a
boxworkspace layout that keeps submitted files immutable while allowing new files to be created in the same working directory - symlink-safe output capture for file outputs and sidecar artifacts
- SPJ and interactive IO judging support for problems that need custom verdict logic or bidirectional contestant/interactor communication
runtime-images.ymlas the source of truth for runtime image groups- Docker build tooling that can emit production multi-language images and single-language CI smoke images from the same YAML catalog
- GitHub Actions CI that runs Go tests, repository policy checks, sandbox
regressions, per-language smoke builds in parallel, and an explicit
plain+python+javamixin smoke job, while publishing one consolidated toolchain summary across production runtime profiles
The runtime catalog lives in runtime-images.yml.
Reusable shared_installs blocks hold toolchains needed by several languages;
each referenced block is expanded once per generated image while direct
language-specific commands keep their declared order.
- Production mode builds grouped images such as
type-ifor common C/C++, Python, PyPy, and Java judge workloads,type-afor lighter scripting and esolang runtimes,type-bfor JVM/Node/Web tooling,type-cfor native and systems toolchains,type-dfor Kotlin,type-efor .NET languages, and dedicated profiles for larger or isolated toolchains such as Julia, Swift, proof assistants, Dart, DuckDB/GDL/Octave, HDL simulators, CUDA Ocelot, Dafny, Isabelle, and Lean. The full production profile table is maintained in docs/architecture.md. - CI mode expands the same catalog into one image per language so that each
smoke job validates a single toolchain in isolation. A separate CI job builds
the production profiles in parallel, runs
scripts/report_toolchain_versions.shonce per profile, records both toolchain versions and language-specific compile options, and uploads the profile summary fragment plus SBOM/scan diagnostics. Docker archive export is currently skipped in CI to conserve runner storage; each profile records an archive diagnostic JSON instead. A final CI job downloads those artifacts, publishes one consolidated GitHub Actions summary, verifies the exact profile and language inventories from the production matrix, binds each summary/SBOM/scan report and its hashes to one immutable image ID, regenerates the aggregate summary for exact comparison, and uploads the exact sorted manifest of summaries, provenance, SBOM/scan evidence, and archives or skip diagnostics as a single bundle. Missing downloads, empty profile sets, failed probes, malformed evidence, and non-portable archive checksum paths fail the summary job. - The current catalog covers native binaries, Python plus bundled judge
libraries (
numpy,pandas,seaborn,matplotlib,Pillow,qiskit,torch,torchvision,jax[cpu], and related dependencies), optional custom Python packages supplied at image build time, PyPy, Java/Kotlin/JVM languages, Node/Deno/TypeScript/CoffeeScript/Elm/ReScript/PureScript, .NET languages, Ruby, PHP, Lua, Perl, Elixir/Erlang/Gleam, Haskell, Idris2, Standard ML, OCaml, SQLite/DuckDB, Go, Rust, Zig, Nim, Pascal, Delphi, Object Pascal, Ada, GNU assembly, NASM, Objective-C/C++, C3, Crystal, D, Hare, Vala, Mojo, Odin, V, FreeBASIC/QBasic, Julia, Swift, R, Racket/Scheme, Mercury, Prolog, Lisp/Smalltalk/GolfScript, APECode, Befunge, Brainfuck, LOLCODE, Whitespace, WASM, Coq/Rocq, Lean, Agda, TLA+, Why3, Isabelle, Aheui, Dart, GDL/Octave, HDL simulation, CUDA Ocelot, Carbon, VB6, Dafny, BQN/APL/J/UIUA/Janet, and UHMLANG. C/C++ and assembly submitters compile into binaries and should target theplainruntime image rather than dedicated native runtime images. Add new languages by extending the YAML file instead of editing shell loops or workflow matrices. - Compile and execute environments set
ONLINE_JUDGE=1. Languages with compiler-supported defines or build tags also receive anONLINE_JUDGEcompile flag where appropriate, such as C/C++/Objective-C, NASM, Rust, Go, Pascal, Nim, D, Dart, Verilog, Crystal, V, Odin, C3, Swift, .NET, Cython, Haxe, and FreeBASIC/QBasic. JVM-family runtime launchers also pass-DONLINE_JUDGE=1. - Debian-based production profiles track
debian:trixie-slim, which raises the default Python, PyPy, and GCC toolchain versions for both production and single-language CI runtime images. - Python judge libraries in the runtime catalog are pinned to exact versions so runtime rebuilds stay reproducible across CI and production.
Inspect the generated matrix:
go run ./cmd/runtime-matrix -mode production
go run ./cmd/runtime-matrix -mode ciDry-run image builds:
./scripts/build_runtime_images.sh -mode production -dry-run -tag-prefix ghcr.io/seo-rii/aonohako
./scripts/build_runtime_images.sh -mode ci -dry-run -tag-prefix aonohako-ciCustom Python packages can be copied into runtime images by passing a directory as a named build context:
./scripts/build_runtime_images.sh \
-mode production \
-only type-i \
-tag-prefix ghcr.io/seo-rii/aonohako \
-python-packages-context /path/to/python/packagesThe same path can be supplied with AONOHAKO_PYTHON_PACKAGES_CONTEXT.
When neither is supplied and the repository python/ directory exists, it is
used by default. Contents are copied to /usr/local/lib/aonohako/python, which
is exported as PYTHONPATH in runtime images. The bundled sitecustomize.py
stays inactive unless an execution requests image sidecar output.
For non-root local development, forward both /compile and /execute to a
hardened runner:
AONOHAKO_DEPLOYMENT_TARGET=dev \
AONOHAKO_EXECUTION_TRANSPORT=remote \
AONOHAKO_SANDBOX_BACKEND=none \
AONOHAKO_REMOTE_RUNNER_URL=https://runner.internal \
go run ./cmd/serverBare go run ./cmd/server uses the compatibility local-dev shape, which is
still an embedded helper sandbox and requires a root parent. If you want the
local root-backed helper sandbox, run it explicitly with a dedicated work root:
sudo env \
AONOHAKO_DEPLOYMENT_TARGET=selfhosted \
AONOHAKO_EXECUTION_TRANSPORT=embedded \
AONOHAKO_SANDBOX_BACKEND=helper \
AONOHAKO_API_BEARER_TOKEN=replace-me \
AONOHAKO_WORK_ROOT=/work \
AONOHAKO_MAX_ACTIVE_RUNS=1 \
go run ./cmd/serverRun the test suite:
go test ./...Validate the current deployment environment without starting the HTTP server:
aonohako-selftest deployment-contractThe deployment contract JSON includes the selected execution shape, whether the
named security contract is implemented, effective and missing local
capabilities, queue and stream limits, inbound/remote auth posture, cgroup
parent presence, whether AONOHAKO_REQUIRE_WORK_ROOT_TMPFS is active, and the
configured AONOHAKO_WORK_ROOT_MAX_BYTES and AONOHAKO_WORK_ROOT_MAX_FILES
values.
Repository deployment tooling can validate its configured ceilings against the
machine-readable deployment-contract.json
manifest before creating a revision.
Checked deployment environment examples live under
docs/examples/: cloudrun-runner.env,
cloudrun-control-plane.env, selfhosted-runner.env, and
dev-control-plane.env.
Repository policy check:
./scripts/check_repo_policy.shSelf-hosted runner hosts can also check future cgroup backend prerequisites:
aonohako-selftest cgroup-preflightPORTdefaults to8080AONOHAKO_DEPLOYMENT_TARGETselects where the server is meant to run:cloudrun,selfhosted, ordev(default)AONOHAKO_EXECUTION_TRANSPORTselects how/compileand/executeare handled:embedded(default) orremoteAONOHAKO_SANDBOX_BACKENDselects the local sandbox implementation:helperornone.containeris a reserved enum value for a future backend and is rejected by startup validation today.- These axes map to explicit security contracts in code:
embedded-helper-process-hardening,remote-control-plane, and reservedreserved-container-isolation. The helper contract is process hardening by default; self-hosted helpers can opt into per-run cgroup memory, pids, and one-vCPU CPU bandwidth limits.aonohako-selftest deployment-contractmoves those cgroup-backed capabilities from missing to effective whenAONOHAKO_CGROUP_PARENTis configured. Mount-namespace, per-run UID, masked/proc, and post-startexecve()isolation remain unavailable in the helper backend. AONOHAKO_EXECUTION_MODEremains as a compatibility shorthand:cloudrun→cloudrun + embedded + helperlocal-root→selfhosted + embedded + helperlocal-dev→dev + embedded + helper(compatibility only; it is not the non-root development path)AONOHAKO_MAX_ACTIVE_RUNSdefaults to1forembedded + helper, stays1forcloudrun, and otherwise defaults tomax(1, cpu-2). Theembedded + helperbackend rejects values other than1.AONOHAKO_MAX_PENDING_QUEUEdefaults to16. Set it explicitly to0only for development cases that intentionally need an unlimited queue.AONOHAKO_MAX_ACTIVE_STREAMSdefaults to64and caps simultaneous/compileand/executerequest streams before they can occupy more server resources. Set it explicitly to0only for development cases that intentionally need unlimited open streams.AONOHAKO_MAX_ACTIVE_UPLOADSdefaults to4outside development andAONOHAKO_MAX_PRINCIPAL_ACTIVE_UPLOADSdefaults to2. These slots are acquired before authentication reads a signed request body, JSON decoding, Base64 validation, or payload URL fetches. The slot is released only after the request enters the bounded run queue or terminates early. Both limits default to0in development; production targets reject0.AONOHAKO_PLATFORM_BODY_HASH_CONCURRENCYdefaults tomin(4, AONOHAKO_MAX_ACTIVE_STREAMS)when streams are bounded, otherwisemin(4, AONOHAKO_MAX_ACTIVE_RUNS)and accepts values from1through64. It separately caps concurrent pre-auth body hashing for signed platform-auth requests, so stream concurrency can be higher than the number of simultaneous 64 MiB body hash operations.AONOHAKO_MAX_PRINCIPAL_ACTIVE_STREAMSdefaults to0fordevand16forcloudrunorselfhosted. It caps simultaneous request streams per authenticated or platform principal;0disables the per-principal cap.AONOHAKO_MAX_PRINCIPAL_REQUESTS_PER_MINUTEdefaults to0fordevand60forcloudrunorselfhosted. It caps accepted/compileand/executerequests per principal per fixed one-minute window. Set it to0on any deployment target to disable the per-process request-rate cap. This is intended for trusted Cloud Run or self-hosted runners whose concurrency and fleet capacity are bounded at the deployment layer.AONOHAKO_HEARTBEAT_INTERVAL_SECdefaults to10AONOHAKO_BODY_READ_TIMEOUT_SECdefaults to30and bounds how long the HTTP server will spend reading one/compileor/executerequest body. This keeps authenticated slow uploads from holding handler goroutines indefinitely before SSE streaming begins.AONOHAKO_REMOTE_SSE_IDLE_TIMEOUT_SECdefaults to30and bounds how long a remote/compileor/executeSSE response may stay silent before the control plane cancels it.AONOHAKO_REMOTE_STRICT_PROTOCOLcontrols whether remote responses must carryX-Aonohako-Protocol-Version. It defaults totrueoutsidedevandfalseindev, so production remote fleets fail closed on unversioned runner responses while local compatibility testing can still accept them.AONOHAKO_ALLOW_REQUEST_NETWORKcontrols whether/executemay honor client-suppliedenable_network=true. It defaults totrueonly fordevandfalseforcloudrunorselfhosted; public runners should route network-enabled problems to an explicitly opted-in runner pool. Outsidedev, enabling it also requiresAONOHAKO_NETWORK_EGRESS_ISOLATED=true, which asserts that the selected embedded runner or downstream remote runner is already inside a deny-by-default network namespace/cgroup-BPF/nftables or equivalent egress boundary that blocks loopback, private, link-local, and metadata addresses. The assertion does not create that infrastructure.AONOHAKO_ALLOW_REQUEST_RUNTIME_PROFILEcontrols whether/compileand/executemay honor request-suppliedruntime_profile. It defaults totrueonly fordevandfalseforcloudrunorselfhosted; production control planes should map problems to policy-owned profiles and enable this only on the trusted runner/control-plane boundary that receives those sanitized requests.AONOHAKO_PROBLEM_RUNTIME_PROFILESmay define a JSON object mapping requestproblem_idvalues to namedAONOHAKO_RUNTIME_TUNING_PROFILES. The server applies the mapped profile before stream or queue acquisition, so public entry points can keep directruntime_profileselection disabled. Withremotetransport, deploy the same profile definitions andproblem_idmapping to the downstream runner whenever the control plane forwards policy-selectedruntime_profilevalues.AONOHAKO_DEFAULT_PYTHON_LIBRARY_MODEselects the request-wide default for Python imports:stdlib(default) orinstalled.stdlibkeeps submitted sibling modules and the standard library available while hiding packages installed in the runtime image.AONOHAKO_ALLOW_REQUEST_PYTHON_INSTALLED_LIBRARIEScontrols whether a request may elevate from thestdlibdefault withpython_library_mode=installed. It defaults totrueonly fordevandfalseforcloudrunorselfhosted. Outside a problem-owned mapping, a request may always choose the saferstdlibmode.AONOHAKO_PROBLEM_PYTHON_LIBRARY_MODESmay define a JSON object mapping requestproblem_idvalues tostdliborinstalled. A problem mapping wins over direct request policy and conflicting request values are rejected before stream or queue admission. Withremotetransport, deploy the same default and problem mappings to the downstream runner, or explicitly allow the trusted runner boundary to receive the control plane's selectedinstalledmode.AONOHAKO_TRUSTED_RUNNER_INGRESSasserts that a root-backed embedded helper runner is reachable only through trusted/private ingress, Cloud Run IAM, mTLS, a gateway, or an equivalent control-plane boundary. It defaults totruefordevand remote control planes, but non-devembedded + helperrunners must set it explicitly totrue.- Numeric environment variables are strict: malformed, negative, or zero values where a positive integer is required fail startup instead of falling back.
AONOHAKO_INBOUND_AUTHcontrols inbound/compileand/executeauthentication. It defaults tononefordevandbearerforcloudrunorselfhosted. Supported values arenonefordevonly,bearer, andplatform.AONOHAKO_API_BEARER_TOKENis required whenAONOHAKO_INBOUND_AUTH=bearer.AONOHAKO_INBOUND_AUTH=platformdocuments that Cloud Run IAM, an API gateway, mTLS, private ingress, or another platform layer authenticates inbound calls before they reach this process. The upstream layer must strip any client-supplied identity headers and rewriteX-Aonohako-Principal; forwarded identity headers such asX-Forwarded-Emailare ignored by the application. Do not expose platform mode directly to the public internet.AONOHAKO_PLATFORM_PRINCIPAL_HMAC_SECRETis required forAONOHAKO_INBOUND_AUTH=platformoutsidedev. It makes platform mode verifyX-Aonohako-Principal-Signature: v4=<hex-hmac-sha256>overmethod + "\n" + request_uri + "\n" + principal + "\n" + timestamp + "\n" + nonce + "\n" + sha256_hex(body)before accepting the request.request_uriincludes the path and query string. The timestamp comes fromX-Aonohako-Principal-Timestampin RFC3339 format and must be within five minutes of the server clock.X-Aonohako-Principal-Noncemust be a fresh, cryptographically random 128-bit value encoded as 32 lowercase hex characters. A bounded replay cache rejects reuse by the same principal until the signature validity window expires; it fails closed when capacity is exhausted. Legacy replayablev3=and bodylessv2=signatures are rejected. Concurrent pre-auth body hashing first requires global and claimed-principal upload admission, and is additionally capped byAONOHAKO_PLATFORM_BODY_HASH_CONCURRENCY, so invalid signatures cannot force unbounded parallel 64 MiB body buffers.AONOHAKO_TRUSTED_PLATFORM_HEADERSandAONOHAKO_PLATFORM_TRUSTED_PROXY_CIDRSremain available only as optional defense-in-depth assertions for deployments that want source-CIDR checks in addition to signed platform principals; unsigned platform headers are not accepted outsidedev.AONOHAKO_WORK_ROOTpoints compile/run directories at a dedicated work root and is required forcloudrun, and forselfhosted + embedded + helperAONOHAKO_REQUIRE_WORK_ROOT_TMPFSis a strict boolean and defaults tofalsefor development and remote control planes. Productionembedded + helperrunners require it to betrue; startup verifies through/proc/self/mountinfothatAONOHAKO_WORK_ROOTis the tmpfs mount point, rather than merely a directory somewhere on a shared tmpfs.AONOHAKO_WORK_ROOT_MAX_BYTES, when nonzero, verifies throughstatfsthat the required work-root filesystem is bounded to that many bytes or less. Production helper runners require a positive value no greater than 1 GiB.AONOHAKO_WORK_ROOT_MAX_FILES, when nonzero, verifies throughstatfsthat the required work-root filesystem exposes no more than that many inodes. Production helper runners require a positive value no greater than 1048576. The Cloud Run in-memory volume advertises that bounded inode ceiling even when its byte size is configured substantially lower.AONOHAKO_CGROUP_PARENTis required forselfhosted + embedded + helperand rejected for other deployment shapes. Startup validates that the parent directory is under a cgroup v2 mount and exposescpu,memory, andpids; each compile/execute/SPJ run is placed in a per-run cgroup withmemory.max,pids.max,cpu.max=100000 100000, andmemory.oom.group=1.GET /livezreports only API-process liveness.GET /readyzadditionally rechecks mandatory work-root and delegated-cgroup invariants and returns503if they disappear.GET /healthzremains a compatibility alias for readiness. These endpoints do not require application authentication.AONOHAKO_REMOTE_RUNNER_URLpointsremotetransport at anotheraonohakorunner service and must be an absolutehttp(s)URL without embedded credentials, query strings, or fragments. Outsidedev, bearer and Cloud Run identity-token authentication require anhttpsURL.AONOHAKO_REMOTE_RUNNER_AUTHcan benone,bearer, orcloudrun-idtoken;noneis allowed only fordevAONOHAKO_REMOTE_RUNNER_TOKENprovides the bearer token whenAONOHAKO_REMOTE_RUNNER_AUTH=bearerAONOHAKO_REMOTE_RUNNER_AUDIENCEoverrides the ID-token audience forcloudrun-idtokenauth; it defaults toAONOHAKO_REMOTE_RUNNER_URL
Per-request execution limits are part of the /execute payload. The
generated public limit table is the canonical numeric
contract:
limits.time_mslimits.memory_mblimits.output_bytesDefaults to64 KiBwhen omitted and is capped internally at8 MiBstdinandexpected_stdoutEach inline field is capped at64 MiBbefore a request enters the shared queue. Usestdin_urlandexpected_stdout_urlto have Aonohako download HTTP(S) payloads server-side instead of embedding them in the JSON body.data_urlsources[],binaries[],programs[].binaries[],spj.binary, andinteractor.binaries[]may use HTTP(S)data_urlinstead ofdata_b64. Server-side payload downloads reject URL credentials and any destination that resolves to loopback, private, link-local, multicast, unspecified, or otherwise reserved address space. The same policy is enforced for every redirect and at connection time. All execute binaries across top-level, program, SPJ, and interactor fields share one request-wide 48 MiB decoded budget across inline and URL-backed payloads. URLs are resolved only after request structure and collection counts pass validation.enable_networkCloud Run embedded-helper runners rejecttrue. Self-hosted embedded-helper runners honor it only whenAONOHAKO_ALLOW_REQUEST_NETWORK=trueandAONOHAKO_NETWORK_EGRESS_ISOLATED=true, and then allow outboundAF_INET/AF_INET6client sockets only; listener syscalls and hostAF_UNIXsockets stay blocked. Control-plane instances can forward networked workloads only to egress-isolated opted-in runners withremotetransport.runtime_profileRequests may select an operator-definedAONOHAKO_RUNTIME_TUNING_PROFILESentry only whenAONOHAKO_ALLOW_REQUEST_RUNTIME_PROFILE=true. Public entry points should keep this disabled and let a trusted control plane attach the profile after applying problem policy.
This repository does not ship cloud-vendor deployment credentials or gcloud
workflow dependencies. The CI policy script fails if common secret-like or
cloud CLI markers are checked in, and it requires Dockerfile base images to be
digest-pinned or routed through digest-pinned build arguments.
The local execution path now enforces these invariants:
- the process working directory is
box/ - each execution workspace root remains server-owned, is assigned to its
sandbox role's GID, and is mode
0710(group traverse only) - submitted files are materialized with immutable permissions (
0444or0555) - the
box/directory is writable so submissions can create new files beside their own sources or binaries - interactive contestants run as UID/GID
65532, while the trusted interactor runs as UID/GID65531behind a different group-traversal boundary; this prevents either peer from traversing or mutating the other's workspace while preserving server ownership of the workspace root, even though the helper backend still shares the host mount and/procnamespaces - captured outputs reject symlinks to avoid read-through escapes
The runtime sandbox uses helper-process hardening rather than mount-based
filesystem isolation. It applies setrlimit, PR_SET_NO_NEW_PRIVS, seccomp,
fd cleanup, immutable submitted files, a writable per-run workspace, and
process-group cleanup. Self-hosted helper deployments can additionally set
AONOHAKO_CGROUP_PARENT to place each compile/execute/SPJ sandbox process in a
per-run cgroup with kernel-enforced memory, pids, and one-vCPU CPU bandwidth
limits.
Verdicts are classified from wall time, target CPU time, procfs RSS samples,
cgroup memory.peak when available, workspace scans, process exit state, and
output/SPJ evaluation in that order. No-cgroup helper runs exclude
rusage.Maxrss because it also contains API-server fork and helper setup memory.
Final run responses include optional verdict_source diagnostics such as
cpu_time, memory_rss, workspace_bytes, file_output, or spj so
operators can see which measurement or judge step selected the status. See
docs/architecture.md for
the exact policy and the remaining environment-dependent boundaries.
Security posture depends on where it runs:
cloudrun + embedded + helperis the supported production security target. Startup fails closed unlessAONOHAKO_WORK_ROOTis configured, writable, not group/world writable, owned by the server UID, the process is running as root,AONOHAKO_TRUSTED_RUNNER_INGRESS=trueis asserted, and the helper queue is single-slot.cloudrun + remote + noneis the supported Cloud Run control-plane shape when/compileand/executeshould be forwarded to a separate hardened runner. It still requires a boundedAONOHAKO_WORK_ROOTbecause the Cloud Run deployment contract requires a dedicated, bounded workspace root; local untrusted compile and execute work is forwarded to the remote runner.selfhosted + embedded + helperapplies the same dedicated work-root contract for local root-backed containers and VMs, includingAONOHAKO_MAX_ACTIVE_RUNS=1because separate requests still reuse the same sandbox UID. Its work root must be a dedicated bounded tmpfs mount with byte and inode ceilings. Because only one request runs at a time, that kernel backing-store ceiling also covers unlinked-open files and write/unlink bursts that directory scanning cannot observe. A delegated cgroup v2 parent is also mandatory, so compiler children and process-spawning runtime wrappers stay inside aggregate CPU, memory, pids, and cleanup accounting. Interactive peers within one request use the distinct fixed role identities described above.dev + remote + noneis the non-root development path. The local server forwards/compileand/executeto a remote hardened runner instead of building or running untrusted inputs locally.dev + embedded + helperremains available through the compatibility mode, but/executestill requires root because the local helper sandbox is root-backed.- for higher-throughput self-hosted deployments, keep helper-backed runners at one active execution each and scale a remote runner pool horizontally instead of increasing helper slots inside one process. See docs/selfhosted.md.
For Cloud Run deployments, use this baseline:
AONOHAKO_DEPLOYMENT_TARGET=cloudrunAONOHAKO_EXECUTION_TRANSPORT=embeddedAONOHAKO_SANDBOX_BACKEND=helperAONOHAKO_API_BEARER_TOKENset to a strong secret, orAONOHAKO_INBOUND_AUTH=platformonly when an upstream layer enforces inbound authenticationAONOHAKO_PLATFORM_PRINCIPAL_HMAC_SECRETwhen using platform auth outsidedevAONOHAKO_TRUSTED_RUNNER_INGRESS=trueafter configuring private ingress, Cloud Run IAM, mTLS, or an equivalent trusted control-plane boundary- second-generation execution environment
- service concurrency
1 - a bounded in-memory volume mounted at a path such as
/work, withAONOHAKO_WORK_ROOT=/work; setAONOHAKO_REQUIRE_WORK_ROOT_TMPFS=truewhen startup should fail unless that path is actually backed bytmpfs, and setAONOHAKO_WORK_ROOT_MAX_BYTESandAONOHAKO_WORK_ROOT_MAX_FILESto the intended volume byte and inode budgets - container memory sized above the work-root byte budget plus runtime headroom, because Cloud Run/no-cgroup runners rely on the outer container limit as the final OOM boundary
- Direct VPC egress with
all-trafficrouting and firewall-denied outbound traffic except for explicitly allowed targets - a dedicated service account with no unnecessary IAM permissions and no baked secrets in the image
For a Cloud Run API/control-plane service that forwards /compile and
/execute, use
AONOHAKO_EXECUTION_TRANSPORT=remote,
AONOHAKO_SANDBOX_BACKEND=none, the same bounded AONOHAKO_WORK_ROOT, and a
private AONOHAKO_REMOTE_RUNNER_URL with AONOHAKO_REMOTE_RUNNER_AUTH=bearer
or AONOHAKO_REMOTE_RUNNER_AUTH=cloudrun-idtoken.
Cloud Run's own documentation states that volumes must be configured through
Cloud Run volume mounts and that arbitrary in-container mounting is not
supported, so aonohako does not depend on cgroup creation or mount-based
filesystem isolation when running there.
The default runtime memory profile is locked down for public judge runners. Operators can narrow selected numeric knobs without passing arbitrary runtime flags through requests:
AONOHAKO_JVM_HEAP_PERCENTcontrols the Java/Kotlin-JVM/Clojure/Groovy/Scala-Xmxshare of the request memory limit. Java-family launchers also set direct-memory and metaspace/class-space caps from the request memory limit. Allowed range:25..75, default50.AONOHAKO_GO_MEMORY_RESERVE_MBsubtracts reserved host/runtime memory from Go-based interpreterGOMEMLIMIT. Allowed range:0..256, default32.AONOHAKO_GO_GOGCcontrols Go GC aggressiveness for Go-based interpreters. Allowed range:10..200, default50.AONOHAKO_ERLANG_SCHEDULERScontrols BEAM scheduler count for Erlang/Elixir. Allowed range:1..4, default1.AONOHAKO_ERLANG_ASYNC_THREADScontrols BEAM async thread count for Erlang/Elixir. Allowed range:0..4, default1.AONOHAKO_DOTNET_GC_HEAP_PERCENTcontrols the .NET GC heap hard-limit share of request memory; the runner converts it toDOTNET_GCHeapHardLimit. Allowed range:25..80, default60. .NET/Dafny use a high finite 2 TiBRLIMIT_FSIZEfloor for CoreCLR/F# compatibility, so their practical disk-burst guard is workspace scanning plus bounded work-root/container storage rather than a tight file-size rlimit.AONOHAKO_KOTLIN_NATIVE_COMPILER_HEAP_MBcontrols Kotlin/Native compiler JVM heap. Allowed range:256..1536, default1024.AONOHAKO_DENO_OLD_SPACE_PERCENTcontrols the Deno/V8 old-space share used for--v8-flags=--max-old-space-size=.... Allowed range:30..75, default60.AONOHAKO_NODE_OLD_SPACE_PERCENTcontrols the Node/V8 old-space share of the request memory limit. Allowed range:30..75, default60.AONOHAKO_NODE_MAX_SEMI_SPACE_MBcaps Node/V8 semi-space. Allowed range:1..16, default8.AONOHAKO_NODE_STACK_SIZE_KBsets Node stack size. Allowed range:512..8192, default2048.AONOHAKO_WASMTIME_MEMORY_GUARD_BYTESsets the Wasmtime guard size. Allowed range:65536..16777216, default65536.AONOHAKO_WASMTIME_MAX_WASM_STACK_BYTESsets the Wasmtime wasm stack cap. Allowed range:262144..8388608, default1048576.AONOHAKO_RUNTIME_TUNING_PROFILESmay define named, policy-owned runtime profiles as a JSON object. Each profile inherits the global tuning values and may override the same bounded numeric keys with snake_case names, for example{"low-memory":{"jvm_heap_percent":35,"node_old_space_percent":45}}./compileand/executemay select one withruntime_profileonly whenAONOHAKO_ALLOW_REQUEST_RUNTIME_PROFILE=true; policy-disabled, unknown, or syntactically invalid profile names are rejected.AONOHAKO_PROBLEM_RUNTIME_PROFILESmaps boundedproblem_idstrings to those named profiles, for example{"contest-1/a":"low-memory"}. A mappedproblem_idapplies the profile even when direct request profile selection is disabled; conflictingruntime_profilevalues are rejected. Remote runner pools should receive the same runtime profile config as the control plane when forwarded requests include policy-selected profiles.
Invalid values fail startup. These settings only tune memory-related runtime caps; they do not expose network, filesystem, process, or arbitrary flag controls to submissions.
For non-Cloud-Run control-plane deployments that should still execute safely, use this baseline:
AONOHAKO_DEPLOYMENT_TARGET=devAONOHAKO_EXECUTION_TRANSPORT=remoteAONOHAKO_SANDBOX_BACKEND=noneAONOHAKO_REMOTE_RUNNER_URL=https://<dedicated-runner>- optional
AONOHAKO_REMOTE_RUNNER_AUTH=bearerwithAONOHAKO_REMOTE_RUNNER_TOKEN=..., orAONOHAKO_REMOTE_RUNNER_AUTH=cloudrun-idtokenwhen calling another Cloud Run service
MIT. See LICENSE.