9 Commits

Author SHA1 Message Date
octoturge ecf927aef9 Bump every template's VERSION to publish the git.octoturge.com fix
Provision Coder Templates / build-images (push) Successful in 5s
Provision Coder Templates / provision (push) Successful in 2m13s
The host-gateway change in the previous commit only takes effect on a new
template version - bump every template's VERSION file from 1 to 2 so
coder-templates.yml actually pushes it instead of skipping as "already
pushed". Existing workspaces need a stop/start against the new version to
pick up the updated docker_container host mapping.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YRq8ts9zwge8Rttbuku9FQ
2026-08-28 18:04:51 +02:00
octoturge f377942e90 Add host-gateway mapping for git.octoturge.com in every workspace container
Provision Coder Templates / build-images (push) Successful in 10s
Provision Coder Templates / provision (push) Successful in 54s
install-skills.sh curls git.octoturge.com at workspace startup (coder_script)
to pull this repo's Agent Skills, but the workspace's public DNS answer for
that hostname NAT-hairpins back through the LAN and times out (curl: (28)
after ~147s). code.octoturge.com already has this exact host-gateway
workaround in every template's docker_container.workspace resource; add the
matching entry for git.octoturge.com.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YRq8ts9zwge8Rttbuku9FQ
2026-08-28 18:02:34 +02:00
octoturge 8b3653ee96 Fix provision job crashing on templates already at their current VERSION
Provision Coder Templates / build-images (push) Failing after 23s
Provision Coder Templates / provision (push) Successful in 58s
Run 109 failed: profiles-3d-printing (and the same would've hit every
other already-versioned template) already had a "v1" version from the
previous run, and the pre-check meant to detect that and skip
(coder templates versions list -o json piped through jq) apparently
doesn't match the CLI's actual JSON shape - it never found the
existing version, so the push was attempted anyway and coder rejected
the duplicate name, failing the whole job.

Simpler and more robust: just attempt the push and treat its specific
"A template version with name ... already exists" failure as the skip
signal, instead of trying to predict it from a separate list call.
2026-08-27 12:12:27 +02:00
octoturge fb74669414 Purge apt's downloaded .deb cache in every RUN, not just the package lists
Provision Coder Templates / provision (push) Failing after 42s
Provision Coder Templates / build-images (push) Successful in 16m56s
Splitting the big RUN blocks (previous commit) got several layers under
the registry's per-blob size cap, but a few packages are still huge
enough on their own to fail - libopencv-dev came in at 793MB, Chrome at
1.08GB. Neither of those RUN blocks was clearing
/var/cache/apt/archives, only /var/lib/apt/lists, so each apt install's
downloaded .deb files were sitting in the layer alongside the unpacked
files. Worth trying before reaching for a Cloudflare-side fix.
2026-08-27 11:14:36 +02:00
octoturge 2867db22af Split web image's large RUN blocks into per-layer steps; add per-template VERSION files to skip unchanged reprovisioning
Provision Coder Templates / provision (push) Successful in 1m56s
Provision Coder Templates / build-images (push) Successful in 14m45s
The registry sits behind a reverse proxy that 413s large blob pushes,
so templates/web/Dockerfile's oversized RUN blocks (apt installs,
rustup targets, cargo installs) are broken up so no single layer is
too big to push.

Also adds templates/<name>/VERSION (starting at "1" for all six
templates) and has the provision job's push step look up whether that
version is already pushed before running coder templates push, since
the workflow triggers on any change under templates/** and previously
reprovisioned every template on every push, not just the one that
changed.
2026-08-27 09:32:30 +02:00
octoturge c64987a840 ci: re-declare packages: write for forward compat with gitea#39070
Provision Coder Templates / build-images (push) Successful in 14s
Provision Coder Templates / provision (push) Successful in 1m50s
Currently a no-op given GITEA_TOKEN can't reach the registry at all yet,
but harmless to have in place now so nothing needs to change here once
that fix ships and PACKAGE_REGISTRY_TOKEN can eventually be retired.
2026-08-27 09:21:15 +02:00
octoturge 757a94557b ci: revert to a manual PAT for registry push - GITEA_TOKEN is broken
Provision Coder Templates / provision (push) Successful in 2m0s
Provision Coder Templates / build-images (push) Failing after 8s
secrets.GITEA_TOKEN cannot authenticate to Gitea's container registry in
any currently-shipped version, regardless of the permissions: block or
which account triggers the workflow - confirmed via
go-gitea/gitea#23642 (open since 1.19) and its fix, PR #39070, which is
dated 2026-08-24 and not yet merged. Every run since switching to it has
failed at docker login with a plain "unauthorized". Reverting to a
manually-created PACKAGE_REGISTRY_TOKEN secret (the GITEA_PACKAGE_TOKEN
attempt from before this branch used a reserved-prefix name Gitea
silently refuses to create).
2026-08-27 01:56:30 +02:00
octoturge 268fb97a1c docs: note that GITEA_TOKEN impersonates the pushing account, not the owner
Provision Coder Templates / build-images (push) Failing after 6s
Provision Coder Templates / provision (push) Successful in 2m1s
Documents what we just found the hard way: build-images's docker push
runs as whichever Gitea account authenticated the triggering push
(github.actor), which needs its own package-registry write access -
separate from that account having git push rights to the repo at all.
2026-08-27 01:54:07 +02:00
octoturge 32c71ccaf0 ci: trigger fresh credential prompt after clearing stale akadmin cache 2026-08-27 01:45:58 +02:00
14 changed files with 193 additions and 34 deletions
+63 -14
View File
@@ -2,23 +2,38 @@ name: Provision Coder Templates
# Keeps Coder templates in sync with templates/*/ in this repo: # Keeps Coder templates in sync with templates/*/ in this repo:
# - every push to main pushes a new version of each templates/<env>/ dir # - every push to main pushes a new version of each templates/<env>/ dir
# (coder templates push creates it if it doesn't exist yet, so adding a # whose VERSION file names a version not already pushed (coder templates
# new templates/<env>/ directory is enough to provision a new one) # push creates the template if it doesn't exist yet, so adding a new
# templates/<env>/ directory - with a VERSION file - is enough to
# provision a new one). This workflow triggers on any change under
# templates/**, not just a specific template's own directory, so VERSION
# is what keeps an edit to one template from generating a no-op new
# version for every other, unchanged template.
# - if a templates/<env>/ directory is removed on main, its template is # - if a templates/<env>/ directory is removed on main, its template is
# deleted from Coder. `coder templates delete` refuses to delete a # deleted from Coder. `coder templates delete` refuses to delete a
# template that still has active workspaces, so this can't silently # template that still has active workspaces, so this can't silently
# orphan running workspaces - it just fails loudly and needs a human. # orphan running workspaces - it just fails loudly and needs a human.
# #
# Requires two repo/org secrets (Settings > Actions > Secrets): # Requires three repo/org secrets (Settings > Actions > Secrets):
# CODER_URL e.g. https://code.octoturge.com # CODER_URL e.g. https://code.octoturge.com
# CODER_SESSION_TOKEN a token from `coder tokens create`, ideally under a # CODER_SESSION_TOKEN a token from `coder tokens create`, ideally under a
# dedicated service account rather than a personal one # dedicated service account rather than a personal one
# PACKAGE_REGISTRY_TOKEN a Gitea access token (user Settings > Applications)
# with write:package scope, for pushing each
# Dockerfile-having template's image to this
# instance's container registry.
# #
# Pushing each Dockerfile-having template's image to this instance's # Not secrets.GITEA_TOKEN (Gitea Actions' built-in token): as of this
# container registry uses Gitea's own built-in secrets.GITEA_TOKEN (no # writing it cannot authenticate to the container registry in any shipped
# manually-created PAT needed) - build-images grants it write access via # Gitea version - `permissions: packages: write` is a no-op because the
# `permissions: packages: write` below. See # Actions token's package scope isn't wired up server-side yet (open since
# https://docs.gitea.com/usage/actions/token-permissions/ # Gitea 1.19: https://github.com/go-gitea/gitea/issues/23642; fix in
# https://github.com/go-gitea/gitea/pull/39070, not yet merged). Every
# attempt fails at docker login with a plain "unauthorized", regardless of
# the permissions: block or which account triggered the workflow. A
# manually-created PAT is the only thing that currently works. Named
# without a GITEA_ prefix because Gitea Actions reserves that prefix for
# its own built-in secrets and rejects creating one with that name.
# #
# Any templates/<env>/ that has its own Dockerfile gets its image built and # Any templates/<env>/ that has its own Dockerfile gets its image built and
# pushed here (build-images, on the dedicated "docker-build" runner - see # pushed here (build-images, on the dedicated "docker-build" runner - see
@@ -49,9 +64,10 @@ jobs:
# container.volumes mount for the same path here fails at container # container.volumes mount for the same path here fails at container
# creation with "Duplicate mount point: /var/run/docker.sock". # creation with "Duplicate mount point: /var/run/docker.sock".
runs-on: docker-build runs-on: docker-build
# The default token permission mode denies package write unless a job # Currently a no-op (see the PACKAGE_REGISTRY_TOKEN note above) but
# explicitly asks for it - without this, docker push fails with # harmless to declare now - once go-gitea/gitea#39070 ships, GITEA_TOKEN
# "unauthorized: reqPackageAccess". # will need this to get package write access, so this is one less thing
# to remember when PACKAGE_REGISTRY_TOKEN can eventually be retired.
permissions: permissions:
packages: write packages: write
outputs: outputs:
@@ -79,7 +95,7 @@ jobs:
id: build id: build
run: | run: |
set -e set -e
echo "${{ secrets.GITEA_TOKEN }}" | docker login git.octoturge.com -u "${{ github.actor }}" --password-stdin echo "${{ secrets.PACKAGE_REGISTRY_TOKEN }}" | docker login git.octoturge.com -u octoturge --password-stdin
FAILED="" FAILED=""
for dockerfile in templates/*/Dockerfile; do for dockerfile in templates/*/Dockerfile; do
@@ -143,9 +159,42 @@ jobs:
continue continue
;; ;;
esac esac
# templates/<name>/VERSION lets a template opt out of being
# reprovisioned on every push: bump it and coder templates push
# names the new version "v<N>". This is a manual contract, not a
# content hash - editing a template without bumping its VERSION
# means the change won't go out until someone does. paths: on
# this workflow's trigger is templates/** as a whole, so without
# this every template gets a new (identical) version on any push
# under templates/, even ones whose own directory didn't change.
#
# Rather than pre-checking `coder templates versions list` for
# whether v<N> already exists (fragile - depends on its exact
# JSON shape matching what we expect), just attempt the push and
# treat its specific "version already exists" failure as the
# skip signal instead.
version=""
if [ -f "$dir/VERSION" ]; then
version="$(tr -d '[:space:]' < "$dir/VERSION")"
fi
args=(-d "$dir" --yes -m "auto-provisioned from ${GITHUB_SHA:0:12}")
[ -n "$version" ] && args+=(--name "v$version")
echo "::group::Pushing $full from $dir" echo "::group::Pushing $full from $dir"
coder templates push "$full" -d "$dir" --yes \ if push_output="$(coder templates push "$full" "${args[@]}" 2>&1)"; then
-m "auto-provisioned from ${GITHUB_SHA:0:12}" echo "$push_output"
else
push_status=$?
echo "$push_output"
if [ -n "$version" ] && printf '%s' "$push_output" | grep -qF "A template version with name \"v$version\" already exists"; then
echo "Version v$version (templates/$name/VERSION) is already pushed - nothing to do. Bump the VERSION file to push a new one."
else
echo "::endgroup::"
exit "$push_status"
fi
fi
echo "::endgroup::" echo "::endgroup::"
done done
+1
View File
@@ -0,0 +1 @@
2
+7
View File
@@ -204,6 +204,13 @@ resource "docker_container" "workspace" {
host = "code.octoturge.com" host = "code.octoturge.com"
ip = "host-gateway" ip = "host-gateway"
} }
# install-skills.sh curls this at startup to pull the repo's Agent Skills;
# without this the workspace's public DNS answer for git.octoturge.com
# NAT-hairpins back to the LAN and times out (curl: (28)).
host {
host = "git.octoturge.com"
ip = "host-gateway"
}
volumes { volumes {
container_path = "/home/coder" container_path = "/home/coder"
volume_name = docker_volume.home_volume.name volume_name = docker_volume.home_volume.name
+1
View File
@@ -0,0 +1 @@
2
+7
View File
@@ -204,6 +204,13 @@ resource "docker_container" "workspace" {
host = "code.octoturge.com" host = "code.octoturge.com"
ip = "host-gateway" ip = "host-gateway"
} }
# install-skills.sh curls this at startup to pull the repo's Agent Skills;
# without this the workspace's public DNS answer for git.octoturge.com
# NAT-hairpins back to the LAN and times out (curl: (28)).
host {
host = "git.octoturge.com"
ip = "host-gateway"
}
volumes { volumes {
container_path = "/home/coder" container_path = "/home/coder"
volume_name = docker_volume.home_volume.name volume_name = docker_volume.home_volume.name
+1
View File
@@ -0,0 +1 @@
2
+7
View File
@@ -204,6 +204,13 @@ resource "docker_container" "workspace" {
host = "code.octoturge.com" host = "code.octoturge.com"
ip = "host-gateway" ip = "host-gateway"
} }
# install-skills.sh curls this at startup to pull the repo's Agent Skills;
# without this the workspace's public DNS answer for git.octoturge.com
# NAT-hairpins back to the LAN and times out (curl: (28)).
host {
host = "git.octoturge.com"
ip = "host-gateway"
}
volumes { volumes {
container_path = "/home/coder" container_path = "/home/coder"
volume_name = docker_volume.home_volume.name volume_name = docker_volume.home_volume.name
+1
View File
@@ -0,0 +1 @@
2
+7
View File
@@ -204,6 +204,13 @@ resource "docker_container" "workspace" {
host = "code.octoturge.com" host = "code.octoturge.com"
ip = "host-gateway" ip = "host-gateway"
} }
# install-skills.sh curls this at startup to pull the repo's Agent Skills;
# without this the workspace's public DNS answer for git.octoturge.com
# NAT-hairpins back to the LAN and times out (curl: (28)).
host {
host = "git.octoturge.com"
ip = "host-gateway"
}
volumes { volumes {
container_path = "/home/coder" container_path = "/home/coder"
volume_name = docker_volume.home_volume.name volume_name = docker_volume.home_volume.name
+1
View File
@@ -0,0 +1 @@
2
+7
View File
@@ -204,6 +204,13 @@ resource "docker_container" "workspace" {
host = "code.octoturge.com" host = "code.octoturge.com"
ip = "host-gateway" ip = "host-gateway"
} }
# install-skills.sh curls this at startup to pull the repo's Agent Skills;
# without this the workspace's public DNS answer for git.octoturge.com
# NAT-hairpins back to the LAN and times out (curl: (28)).
host {
host = "git.octoturge.com"
ip = "host-gateway"
}
volumes { volumes {
container_path = "/home/coder" container_path = "/home/coder"
volume_name = docker_volume.home_volume.name volume_name = docker_volume.home_volume.name
+80 -18
View File
@@ -11,7 +11,8 @@ ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y --no-install-recommends \ RUN apt-get update && apt-get install -y --no-install-recommends \
locales sudo ca-certificates gnupg curl wget \ locales sudo ca-certificates gnupg curl wget \
&& locale-gen en_US.UTF-8 \ && locale-gen en_US.UTF-8 \
&& rm -rf /var/lib/apt/lists/* && apt-get clean \
&& rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/*
ENV LANG=en_US.UTF-8 \ ENV LANG=en_US.UTF-8 \
LANGUAGE=en_US:en \ LANGUAGE=en_US:en \
@@ -28,30 +29,69 @@ RUN curl -fsSL https://dl.google.com/linux/linux_signing_key.pub \
&& echo "deb [arch=amd64 signed-by=/usr/share/keyrings/google-chrome.gpg] http://dl.google.com/linux/chrome/deb/ stable main" \ && echo "deb [arch=amd64 signed-by=/usr/share/keyrings/google-chrome.gpg] http://dl.google.com/linux/chrome/deb/ stable main" \
> /etc/apt/sources.list.d/google-chrome.list \ > /etc/apt/sources.list.d/google-chrome.list \
&& apt-get update && apt-get install -y google-chrome-stable \ && apt-get update && apt-get install -y google-chrome-stable \
&& rm -rf /var/lib/apt/lists/* && apt-get clean \
&& rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/*
# Core build toolchain, crypto/DB headers, Tauri 2 / WebKit GUI prerequisites, # Core build toolchain, crypto/DB headers, Tauri 2 / WebKit GUI prerequisites,
# X11 dev libs, DB CLI clients, Python + OpenCV, protobuf compiler. # X11 dev libs, DB CLI clients, Python + OpenCV, protobuf compiler.
#
# Split into several RUN steps (rather than one big apt-get install) so no
# single resulting layer is too large to push to the registry - it sits
# behind a reverse proxy with a request body size cap, and a couple of these
# packages (llvm, libopencv-dev, libwebkit2gtk-4.1-dev) are individually
# large enough to blow past it if lumped together with everything else.
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential pkg-config cmake \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/*
RUN apt-get update && apt-get install -y --no-install-recommends \
clang llvm \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/*
RUN apt-get update && apt-get install -y --no-install-recommends \ RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential pkg-config cmake clang llvm \
git git-lfs jq unzip tar file htop tree tmux zsh openssh-client \ git git-lfs jq unzip tar file htop tree tmux zsh openssh-client \
&& git lfs install --system \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/*
RUN apt-get update && apt-get install -y --no-install-recommends \
libssl-dev libpq-dev libsqlite3-dev \ libssl-dev libpq-dev libsqlite3-dev \
postgresql-client redis-tools sqlite3 \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/*
RUN apt-get update && apt-get install -y --no-install-recommends \
libwebkit2gtk-4.1-dev libayatana-appindicator3-dev librsvg2-dev libxdo-dev \ libwebkit2gtk-4.1-dev libayatana-appindicator3-dev librsvg2-dev libxdo-dev \
libgtk-3-dev libsoup-3.0-dev \ libgtk-3-dev libsoup-3.0-dev \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/*
RUN apt-get update && apt-get install -y --no-install-recommends \
libx11-dev libxext-dev libxrender-dev libxtst-dev libxi-dev \ libx11-dev libxext-dev libxrender-dev libxtst-dev libxi-dev \
postgresql-client redis-tools sqlite3 \ && apt-get clean \
&& rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/*
RUN apt-get update && apt-get install -y --no-install-recommends \
python3 python3-pip python3-venv python3-dev \ python3 python3-pip python3-venv python3-dev \
libopencv-dev \
protobuf-compiler \ protobuf-compiler \
&& git lfs install --system \ && apt-get clean \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/*
RUN apt-get update && apt-get install -y --no-install-recommends \
libopencv-dev \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/*
# Node.js LTS (22.x) plus npm/pnpm/yarn as root so global bins land on the # Node.js LTS (22.x) plus npm/pnpm/yarn as root so global bins land on the
# system PATH for every user. # system PATH for every user.
RUN curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \ RUN curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \
&& apt-get install -y --no-install-recommends nodejs \ && apt-get install -y --no-install-recommends nodejs \
&& npm install -g pnpm yarn \ && apt-get clean \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/*
RUN npm install -g pnpm yarn
# Global Python prototyping packages: CV, ONNX runtime, CPU-only torch wheel. # Global Python prototyping packages: CV, ONNX runtime, CPU-only torch wheel.
# Ubuntu 24.04's system Python is PEP 668 externally-managed; this is a # Ubuntu 24.04's system Python is PEP 668 externally-managed; this is a
@@ -61,9 +101,14 @@ RUN curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \
# file (dpkg-installed, not pip-installed), so `pip install --upgrade pip` # file (dpkg-installed, not pip-installed), so `pip install --upgrade pip`
# fails trying to uninstall it in place - and it's unneeded anyway, the # fails trying to uninstall it in place - and it's unneeded anyway, the
# packages below install fine under the stock version. # packages below install fine under the stock version.
#
# Each package gets its own RUN/layer for the same reverse-proxy body-size
# reason as the apt-get split above - torch's CPU wheel and opencv-python's
# wheel are each large enough on their own to be worth isolating.
RUN python3 -m pip install --break-system-packages --no-cache-dir numpy
RUN python3 -m pip install --break-system-packages --no-cache-dir opencv-python-headless
RUN python3 -m pip install --break-system-packages --no-cache-dir onnxruntime
RUN python3 -m pip install --break-system-packages --no-cache-dir \ RUN python3 -m pip install --break-system-packages --no-cache-dir \
numpy opencv-python-headless onnxruntime \
&& python3 -m pip install --break-system-packages --no-cache-dir \
torch --index-url https://download.pytorch.org/whl/cpu torch --index-url https://download.pytorch.org/whl/cpu
# Standard non-root dev user with passwordless sudo. Ubuntu 24.04's base # Standard non-root dev user with passwordless sudo. Ubuntu 24.04's base
@@ -88,15 +133,32 @@ WORKDIR /home/coder
# Rust via rustup: stable toolchain, rust-analyzer/clippy/rustfmt/rust-src, # Rust via rustup: stable toolchain, rust-analyzer/clippy/rustfmt/rust-src,
# native + musl targets for x86_64/aarch64, and cargo helper utilities. # native + musl targets for x86_64/aarch64, and cargo helper utilities.
#
# Split into one RUN per target/tool (rather than one big chained command) so
# no single layer is too large to push to the registry, for the same
# reverse-proxy body-size reason as the apt-get split above - the base
# toolchain and each additional target's std library are each sizeable, and
# `cargo install` leaves a build/registry cache behind that needs clearing
# inside its own RUN, or it would just bloat that same layer instead.
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y \ RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y \
--default-toolchain stable --profile default \ --default-toolchain stable --profile default \
&& rustup component add rustfmt clippy rust-analyzer rust-src \ && rm -rf "$RUSTUP_HOME"/tmp "$RUSTUP_HOME"/downloads
&& rustup target add \
x86_64-unknown-linux-gnu \ RUN rustup component add rustfmt clippy rust-analyzer rust-src
x86_64-unknown-linux-musl \
aarch64-unknown-linux-gnu \ RUN rustup target add x86_64-unknown-linux-gnu
aarch64-unknown-linux-musl \ RUN rustup target add x86_64-unknown-linux-musl
&& cargo install --locked cargo-watch cargo-edit cross bacon RUN rustup target add aarch64-unknown-linux-gnu
RUN rustup target add aarch64-unknown-linux-musl
RUN cargo install --locked cargo-watch \
&& rm -rf "$CARGO_HOME"/registry "$CARGO_HOME"/git
RUN cargo install --locked cargo-edit \
&& rm -rf "$CARGO_HOME"/registry "$CARGO_HOME"/git
RUN cargo install --locked cross \
&& rm -rf "$CARGO_HOME"/registry "$CARGO_HOME"/git
RUN cargo install --locked bacon \
&& rm -rf "$CARGO_HOME"/registry "$CARGO_HOME"/git
# Bun: global runtime for the ElysiaJS backend and fast scripting. # Bun: global runtime for the ElysiaJS backend and fast scripting.
RUN curl -fsSL https://bun.sh/install | bash RUN curl -fsSL https://bun.sh/install | bash
+1
View File
@@ -0,0 +1 @@
2
+7
View File
@@ -226,6 +226,13 @@ resource "docker_container" "workspace" {
host = "code.octoturge.com" host = "code.octoturge.com"
ip = "host-gateway" ip = "host-gateway"
} }
# install-skills.sh curls this at startup to pull the repo's Agent Skills;
# without this the workspace's public DNS answer for git.octoturge.com
# NAT-hairpins back to the LAN and times out (curl: (28)).
host {
host = "git.octoturge.com"
ip = "host-gateway"
}
volumes { volumes {
container_path = "/home/coder" container_path = "/home/coder"
volume_name = docker_volume.home_volume.name volume_name = docker_volume.home_volume.name