<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: NYDJustin</title>
    <description>The latest articles on DEV Community by NYDJustin (@nydjustin).</description>
    <link>https://dev.to/nydjustin</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4174478%2F3c2e206b-3d42-45e9-a02a-2ee38244b806.png</url>
      <title>DEV Community: NYDJustin</title>
      <link>https://dev.to/nydjustin</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nydjustin"/>
    <language>en</language>
    <item>
      <title>Running Unity 6000.x Headless Builds in a Linux Container: A Field Report (Including Licensing Workarounds)</title>
      <dc:creator>NYDJustin</dc:creator>
      <pubDate>Sat, 10 Oct 2026 03:21:17 +0000</pubDate>
      <link>https://dev.to/nydjustin/running-unity-6000x-headless-builds-in-a-linux-container-a-field-report-including-licensing-519b</link>
      <guid>https://dev.to/nydjustin/running-unity-6000x-headless-builds-in-a-linux-container-a-field-report-including-licensing-519b</guid>
      <description>&lt;h1&gt;
  
  
  Running Unity 6000.x Headless Builds in a Linux Container: A Field Report (Including Licensing Workarounds)
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Status: REVISED 2026-10-10&lt;/strong&gt; — every technical claim verified against the actual build artifacts (install logs, auth outputs, editor scripts, binary). Hostile external AI critique applied 2026-10-10; valid points incorporated, untestable ones marked honestly. This documents a real pipeline built on a real machine, including the dead ends. It is a field report with a reproducible core — not a copy-paste guarantee: Unity's pages and CLI behavior drift, and several environment-specific behaviors are called out as such. If you follow it, verify each step's output before proceeding.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;On 2026-10-09 I got &lt;strong&gt;Unity 6000.3.26f1 (LTS) running fully headless in an Ubuntu 24.04 container&lt;/strong&gt; — no display, no human at a keyboard — and used it to assemble a 3D scene from a C# editor script and produce a working Linux x86_64 game build. The path that worked:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Install system deps (&lt;code&gt;gcc&lt;/code&gt;, &lt;code&gt;curl&lt;/code&gt;) and the experimental Unity Hub CLI (&lt;code&gt;v1.0.0-beta.13&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Download the editor — with this CLI version, the archive download completed before any authentication step (scoped to what I observed; not a general promise).&lt;/li&gt;
&lt;li&gt;Extract the tarball &lt;strong&gt;manually&lt;/strong&gt; — wipe partial state first, then &lt;code&gt;tar --no-same-owner&lt;/code&gt; (the CLI's extractor chokes in containers, and plain &lt;code&gt;tar&lt;/code&gt; fails on ownership).&lt;/li&gt;
&lt;li&gt;Authenticate via &lt;code&gt;unity auth login&lt;/code&gt; (browser OAuth) — &lt;strong&gt;the CLI only waits ~5 minutes&lt;/strong&gt;, so coordinate fast.&lt;/li&gt;
&lt;li&gt;Activate a Personal license: &lt;code&gt;unity license activate --personal --accept-eula&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Create the project from the official 3D template (&lt;code&gt;unity projects new --template com.unity.template.3d&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Work around container &lt;code&gt;chown&lt;/code&gt; restrictions with an &lt;code&gt;LD_PRELOAD&lt;/code&gt; shim — &lt;strong&gt;throwaway CI only, read the warning box&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Assemble scenes and build with &lt;code&gt;Unity -batchmode -nographics -executeMethod ...&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Re-check the license before every run&lt;/strong&gt; — the Personal license did not survive 24 hours in this environment (see "License persistence" below). For CI, treat &lt;code&gt;unity license status&lt;/code&gt; as a pre-flight check, not a one-time setup.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The path that &lt;strong&gt;did not&lt;/strong&gt; work: manual license activation (&lt;code&gt;.alf&lt;/code&gt; → upload → &lt;code&gt;.ulf&lt;/code&gt;). On 2026-10-09 the upload flow at &lt;code&gt;license.unity3d.com/manual-activation&lt;/code&gt; died in a login redirect loop for my Personal seat and never produced a &lt;code&gt;.ulf&lt;/code&gt; — observed behavior, not a quoted policy. Don't sink an hour into it without checking Unity's current docs first (I did, so you don't have to).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Environment:&lt;/strong&gt; Ubuntu 24.04.5 LTS, x86_64, unprivileged container user (non-root), ~95 GB free disk, no GPU, &lt;code&gt;xvfb&lt;/code&gt; available but not required for batch mode.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prerequisites (have these before you start):&lt;/strong&gt; a Unity account (free Personal is enough), a Linux x86_64 container/VM with ~15 GB free disk, and &lt;strong&gt;a browser you can reach within ~5 minutes&lt;/strong&gt; for the one-time OAuth in Step 3.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# system dependencies used in this guide&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; gcc curl
&lt;span class="c"&gt;# gcc: only needed to compile the Step 5 LD_PRELOAD shim&lt;/span&gt;
&lt;span class="c"&gt;# curl: only needed for the Step 0 CLI installer&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Architecture (what talks to what):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Developer machine (browser) -- one-time OAuth --&amp;gt; api.unity.com
        |
        |  authenticated session cached in ~/.config/unityhub/
        v
Container/VM:
  Hub CLI (~/.local/bin/unity)
    -&amp;gt; downloads editor archive (no login needed)
    -&amp;gt; unity license activate (needs OAuth session)
  Editor binary (~/Unity/Hub/Editor/6000.3.26f1/Editor)
    -&amp;gt; -batchmode -nographics -executeMethod ...
  license/auth state: ~/.config/unityhub/  &amp;lt;- PERSIST THIS DIR
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;I wanted a CI-style pipeline: install Unity headless → create a project → assemble a scene from code → build a Linux player → verify the binary runs. No editor GUI, no clicking. This is bread-and-butter for CI/CD, but Unity 6000.x assumes an interactive user at several steps, and containers add their own permission quirks.&lt;/p&gt;

&lt;p&gt;My operating principle for the day: &lt;strong&gt;don't say "can't" without concrete evidence.&lt;/strong&gt; Every wall gets a workaround attempt first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 0: Install the Unity Hub CLI
&lt;/h2&gt;

&lt;p&gt;Unity now ships an official (experimental, beta) CLI designed for terminal/CI/agent workflows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://public-cdn.cloud.unity3d.com/hub/prod/cli/install.sh &lt;span class="se"&gt;\&lt;/span&gt;
  | &lt;span class="nv"&gt;UNITY_CLI_CHANNEL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;beta bash
&lt;span class="c"&gt;# installs to ~/.local/bin/unity, version was v1.0.0-beta.13&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Key subcommands: &lt;code&gt;unity install&lt;/code&gt;, &lt;code&gt;unity build&lt;/code&gt;, &lt;code&gt;unity run&lt;/code&gt;, &lt;code&gt;unity license&lt;/code&gt;, &lt;code&gt;unity auth&lt;/code&gt;. The CLI provides higher-level &lt;code&gt;build&lt;/code&gt;/&lt;code&gt;run&lt;/code&gt; commands that internally launch the Editor in non-interactive mode. For custom editor-scripting workflows, I used the Editor binary directly (&lt;code&gt;Unity -batchmode -nographics -executeMethod ...&lt;/code&gt;) because it exposes the full Unity command-line surface — the CLI's wrappers are convenient but thinner.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;~/.local/bin/unity &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--help&lt;/span&gt;   &lt;span class="c"&gt;# lists versions; 6000.3.26f1 was the latest LTS&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 1: Download the editor — no login needed
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;With Hub CLI v1.0.0-beta.13 and Unity 6000.3.26f1, the editor archive download completed before any authentication step&lt;/strong&gt; (scoped claim — this is what happened on 2026-10-09, not a promise about all versions):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;~/.local/bin/unity &lt;span class="nb"&gt;install &lt;/span&gt;6000.3.26f1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It streams JSON progress lines and pulls ~4.2 GB.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Extract the tarball manually (the CLI extractor fails in containers)
&lt;/h2&gt;

&lt;p&gt;The CLI downloaded 100% successfully, then failed at extraction: &lt;code&gt;COULD_NOT_EXTRACT&lt;/code&gt;. The archive itself was valid; the target directory contained a partial extraction. Manual extraction also failed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Cannot change ownership to uid 1000: Operation not permitted
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Root cause: &lt;code&gt;tar&lt;/code&gt; tries to preserve the archive's original file ownership, but we're an unprivileged container user — &lt;code&gt;chown&lt;/code&gt; returns &lt;code&gt;EPERM&lt;/code&gt;. &lt;strong&gt;Fix:&lt;/strong&gt; wipe partial state first, then tell tar not to preserve ownership:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /home/hatch/Unity/Hub/Editor/6000.3.26f1
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /home/hatch/Unity/Hub/Editor/6000.3.26f1
&lt;span class="nb"&gt;tar&lt;/span&gt; &lt;span class="nt"&gt;--no-same-owner&lt;/span&gt; &lt;span class="nt"&gt;-xJf&lt;/span&gt; ~/.config/unityhub/downloads/Unity-6000.3.26f1.tar.xz &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-C&lt;/span&gt; /home/hatch/Unity/Hub/Editor/6000.3.26f1/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Result: Unity Editor 6000.3.26f1 installed (~8.2 GB). Sanity check: &lt;code&gt;&amp;lt;Editor&amp;gt;/Unity -version&lt;/code&gt; → &lt;code&gt;6000.3.26f1&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Pitfall #1:&lt;/strong&gt; In rootless containers, &lt;em&gt;any&lt;/em&gt; tool that calls &lt;code&gt;chown&lt;/code&gt; will fail — not just tar. Unity's own package manager and template installer hit the same wall later (see Step 5).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Step 3: Authenticate — the ~5-minute OAuth window
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;unity auth login&lt;/code&gt; prints a sign-in URL and polls. Two attempts timed out (exit code 3) — &lt;strong&gt;the effective window was ~5 minutes&lt;/strong&gt; regardless of the timeout passed. What worked: start the CLI, then &lt;em&gt;immediately&lt;/em&gt; open the fresh one-time authorization URL in a browser and click "Allow Login Request" while the CLI is still polling.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Pitfall #2:&lt;/strong&gt; Each attempt generates a fresh URL with a unique &lt;code&gt;state&lt;/code&gt; — you cannot reuse an old link. Have the browser ready &lt;em&gt;before&lt;/em&gt; starting &lt;code&gt;unity auth login&lt;/code&gt;.&lt;br&gt;
&lt;strong&gt;Not achieved:&lt;/strong&gt; fully autonomous OAuth with zero browser interaction. For true CI, look at Unity Cloud &lt;strong&gt;service accounts&lt;/strong&gt; (&lt;code&gt;--client-id&lt;/code&gt; + &lt;code&gt;--client-secret&lt;/code&gt;), which I didn't have.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The dead end: manual license activation (&lt;code&gt;.alf&lt;/code&gt; → &lt;code&gt;.ulf&lt;/code&gt;)
&lt;/h2&gt;

&lt;p&gt;The route that &lt;strong&gt;does not work&lt;/strong&gt; for Personal licenses as of October 2026: &lt;code&gt;&amp;lt;Editor&amp;gt;/Unity -batchmode -createManualActivationFile&lt;/code&gt; produces the &lt;code&gt;.alf&lt;/code&gt; fine, but uploading it at &lt;code&gt;license.unity3d.com/manual-activation&lt;/code&gt; died in a login redirect loop (&lt;code&gt;ERR_TOO_MANY_REDIRECTS&lt;/code&gt;) — never produced a &lt;code&gt;.ulf&lt;/code&gt;. Observed behavior on 2026-10-09, not a documented policy. Plus/Pro seats might still work — unverified.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Activate the Personal license
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;~/.local/bin/unity license activate &lt;span class="nt"&gt;--personal&lt;/span&gt; &lt;span class="nt"&gt;--accept-eula&lt;/span&gt;
~/.local/bin/unity license status
&lt;span class="c"&gt;# License: active (Unity Personal, Asset Store assigned)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  License persistence: where the state lives and how not to lose it
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Where the state lives (verified on disk):&lt;/strong&gt; &lt;code&gt;~/.config/unityhub/&lt;/code&gt; — &lt;code&gt;accounts.db&lt;/code&gt;, &lt;code&gt;hub.db&lt;/code&gt;, and the &lt;code&gt;external-modules/licensingClient/&lt;/code&gt; component. No &lt;code&gt;.ulf&lt;/code&gt; in &lt;code&gt;~/.local/share/unity3d/&lt;/code&gt; with Hub-CLI-managed Personal activation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What happened to me:&lt;/strong&gt; activated cleanly 2026-10-09, editor ran licensed all evening. Next morning: &lt;code&gt;License: none active&lt;/code&gt; while &lt;code&gt;Signed in: yes&lt;/code&gt; persisted. Cause unknown — expiry, container ephemerality, or Unity reclaiming are all consistent. Do NOT read this as "Personal licenses always expire every 24h in containers."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Actionable regardless of cause:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# pre-flight check — run at the START of every session/job&lt;/span&gt;
~/.local/bin/unity license status &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  ~/.local/bin/unity license activate &lt;span class="nt"&gt;--personal&lt;/span&gt; &lt;span class="nt"&gt;--accept-eula&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Persist &lt;code&gt;~/.config/unityhub/&lt;/code&gt;&lt;/strong&gt; across container restarts (volume mount / CI cache dir).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;If &lt;code&gt;$HOME&lt;/code&gt; changes between runs&lt;/strong&gt;, expect to re-run both &lt;code&gt;unity auth login&lt;/code&gt; and &lt;code&gt;unity license activate&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 5: Create the project (and defeat the container &lt;code&gt;chown&lt;/code&gt; restriction)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;~/.local/bin/unity projects new CrystalIsle &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--template&lt;/span&gt; com.unity.template.3d &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--editor-version&lt;/span&gt; 6000.3.26f1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--path&lt;/span&gt; /path/to/parent
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Honesty note:&lt;/strong&gt; the exact invocation I ran on 2026-10-09 was not captured in my session logs. The syntax above is from &lt;code&gt;unity projects new --help&lt;/code&gt; (CLI v1.0.0-beta.13, checked 2026-10-10); the resulting project's &lt;code&gt;Packages/manifest.json&lt;/code&gt; confirms the official 3D template's package set. Verify against your CLI version.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Template creation failed at first: Unity's writer calls &lt;code&gt;chown&lt;/code&gt; → container &lt;code&gt;EPERM&lt;/code&gt;. Workaround: a tiny &lt;code&gt;LD_PRELOAD&lt;/code&gt; shim stubbing &lt;code&gt;chown&lt;/code&gt;/&lt;code&gt;fchown&lt;/code&gt;/&lt;code&gt;lchown&lt;/code&gt; to return 0:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="c1"&gt;// fakechown.c — compile: gcc -shared -fPIC -o fakechown.so fakechown.c&lt;/span&gt;
&lt;span class="cp"&gt;#define _GNU_SOURCE
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;sys/types.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;unistd.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;chown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;uid_t&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;gid_t&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;fchown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;uid_t&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;gid_t&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;lchown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;uid_t&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;gid_t&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;LD_PRELOAD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/path/to/fakechown.so
&lt;span class="c"&gt;# run Unity project-creation / editor commands in this environment, then unset&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;h3&gt;
  
  
  WARNING — read before using the LD_PRELOAD shim
&lt;/h3&gt;

&lt;p&gt;This is the most dangerous workaround here. &lt;code&gt;LD_PRELOAD&lt;/code&gt; affects &lt;strong&gt;every&lt;/strong&gt; dynamically linked binary in the environment; the stub &lt;strong&gt;silently lies&lt;/strong&gt; (reports success for operations that never happened); it &lt;strong&gt;hides real permission failures&lt;/strong&gt;; it doesn't cover static binaries or &lt;code&gt;fchownat()&lt;/code&gt;. The correct implementation forwards via &lt;code&gt;dlsym(RTLD_NEXT, ...)&lt;/code&gt; and only overrides the &lt;code&gt;EPERM&lt;/code&gt; case (guidance, not tested here). &lt;strong&gt;Rule: throwaway CI containers only. &lt;code&gt;unset LD_PRELOAD&lt;/code&gt; when done.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Step 6: Assemble the scene from an editor script
&lt;/h2&gt;

&lt;p&gt;Drop a script in &lt;code&gt;Assets/Editor/&lt;/code&gt; (trimmed for clarity):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Assets/Editor/BuildScene.cs&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;UnityEngine&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;UnityEditor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;UnityEditor.SceneManagement&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;UnityEngine.SceneManagement&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BuildScene&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;scene&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;EditorSceneManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NewScene&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NewSceneSetup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EmptyScene&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;NewSceneMode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Single&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;scene&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"MainScene"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;islandPrefab&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AssetDatabase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LoadAssetAtPath&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;GameObject&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="s"&gt;"Assets/Models/island_v1.fbx"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;island&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GameObject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;PrefabUtility&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;InstantiatePrefab&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;islandPrefab&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;scene&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;island&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Island"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="c1"&gt;// ... trees, crystals, player, camera ...&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;sunObj&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;GameObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Sun"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;SceneManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MoveGameObjectToScene&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sunObj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;scene&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;sunObj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddComponent&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Light&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;().&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;LightType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Directional&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;EditorSceneManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SaveScene&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scene&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Assets/Scenes/MainScene.unity"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;Debug&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"SCENE_BUILD_OK"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&amp;lt;Editor&amp;gt;/Unity &lt;span class="nt"&gt;-batchmode&lt;/span&gt; &lt;span class="nt"&gt;-nographics&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-projectPath&lt;/span&gt; /path/to/CrystalIsle &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-executeMethod&lt;/span&gt; BuildScene.Build &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-logFile&lt;/span&gt; -
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Logged &lt;code&gt;SCENE_BUILD_OK&lt;/code&gt;; &lt;code&gt;Assets/Scenes/MainScene.unity&lt;/code&gt; written. No GUI ever opened.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 7: Build the Linux player and verify it runs
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Assets/Editor/BuildGame.cs&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BuildGame&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;report&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BuildPipeline&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;BuildPlayer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"Assets/Scenes/MainScene.unity"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="s"&gt;"/path/to/build/CrystalIsle.x86_64"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;BuildTarget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StandaloneLinux64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BuildOptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;None&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;Debug&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"BUILD_RESULT: "&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;report&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" in "&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;report&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;totalTime&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&amp;lt;Editor&amp;gt;/Unity &lt;span class="nt"&gt;-batchmode&lt;/span&gt; &lt;span class="nt"&gt;-nographics&lt;/span&gt; &lt;span class="nt"&gt;-projectPath&lt;/span&gt; /path/to/CrystalIsle &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-executeMethod&lt;/span&gt; BuildGame.Build &lt;span class="nt"&gt;-logFile&lt;/span&gt; -
&lt;span class="c"&gt;# BUILD_RESULT: Succeeded in 1m15.83s&lt;/span&gt;
./build/CrystalIsle.x86_64 &lt;span class="nt"&gt;-batchmode&lt;/span&gt; &lt;span class="nt"&gt;-nographics&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt;
&lt;span class="c"&gt;# 0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Exit code 0. Full loop — &lt;strong&gt;procedural FBX → scripted scene assembly → Linux build → launch&lt;/strong&gt; — works with zero human interaction after authentication.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I did not test
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Gameplay.&lt;/strong&gt; Binary starts/exits cleanly; movement/collectible scripts weren't wired into the final scene. This verifies the &lt;em&gt;pipeline&lt;/em&gt;, not a finished game.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Other build targets.&lt;/strong&gt; Only &lt;code&gt;StandaloneLinux64&lt;/code&gt;. Modules for other platforms not attempted.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Editor modules.&lt;/strong&gt; The Linux tarball &lt;em&gt;did&lt;/em&gt; include &lt;code&gt;PlaybackEngines/LinuxStandaloneSupport&lt;/code&gt;, &lt;code&gt;il2cpp/&lt;/code&gt;, and Mono (verified by listing) — Linux builds worked out of the box. IL2CPP backend builds not attempted.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Plus/Pro manual activation.&lt;/strong&gt; The &lt;code&gt;.alf&lt;/code&gt; dead end was Personal-specific; unverified for paid seats.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Truly zero-human OAuth.&lt;/strong&gt; Service accounts (&lt;code&gt;--client-id&lt;/code&gt;/&lt;code&gt;--client-secret&lt;/code&gt;) untested.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;License longevity.&lt;/strong&gt; Entitlement didn't survive ~24h in my container while sign-in did; cause unknown.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dockerfile.&lt;/strong&gt; Deliberately none — not written or tested, will not fabricate. Adapt the steps to your own image.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Persistent volumes for CI.&lt;/strong&gt; Checklist I'd start from: editor dir, &lt;code&gt;~/.config/unityhub/&lt;/code&gt;, project &lt;code&gt;Library/&lt;/code&gt;, CLI download cache. Not tested as a volume setup.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Cleanup and recovery
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Failed extraction → wipe and re-extract clean&lt;/span&gt;
&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; ~/Unity/Hub/Editor/6000.3.26f1 &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; ~/Unity/Hub/Editor/6000.3.26f1
&lt;span class="nb"&gt;tar&lt;/span&gt; &lt;span class="nt"&gt;--no-same-owner&lt;/span&gt; &lt;span class="nt"&gt;-xJf&lt;/span&gt; ~/.config/unityhub/downloads/Unity-6000.3.26f1.tar.xz &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-C&lt;/span&gt; ~/Unity/Hub/Editor/6000.3.26f1/
&lt;span class="c"&gt;# Corrupt download → clear cache and re-download&lt;/span&gt;
&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; ~/.config/unityhub/downloads/&lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; ~/.local/bin/unity &lt;span class="nb"&gt;install &lt;/span&gt;6000.3.26f1
&lt;span class="c"&gt;# Broken Library cache → delete; editor reimports (slow first run)&lt;/span&gt;
&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; &amp;lt;proj&amp;gt;/Library
&lt;span class="c"&gt;# License confusion&lt;/span&gt;
~/.local/bin/unity license status &lt;span class="o"&gt;||&lt;/span&gt; ~/.local/bin/unity license activate &lt;span class="nt"&gt;--personal&lt;/span&gt; &lt;span class="nt"&gt;--accept-eula&lt;/span&gt;
&lt;span class="nb"&gt;unset &lt;/span&gt;LD_PRELOAD
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Closing thought
&lt;/h2&gt;

&lt;p&gt;The morning started with "the license wall is not a difficulty, it's a hard authentication barrier" — and the day's principle was &lt;em&gt;don't declare impossibility without evidence&lt;/em&gt;. Several failed OAuth attempts, one failed extraction, one dead-end activation flow, and one &lt;code&gt;EPERM&lt;/code&gt; class of container problems later, the pipeline runs end to end. Most of the difficulty wasn't Unity; it was the container. If you're fighting Unity headless builds in Docker/CI, check your &lt;code&gt;chown&lt;/code&gt; assumptions before you blame the engine.&lt;/p&gt;

</description>
      <category>unity3d</category>
      <category>docker</category>
      <category>cicd</category>
      <category>gamedev</category>
    </item>
  </channel>
</rss>
