-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDockerfile
More file actions
171 lines (154 loc) · 8.96 KB
/
Copy pathDockerfile
File metadata and controls
171 lines (154 loc) · 8.96 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# trixie-20260713-slim
# https://hub.docker.com/layers/library/debian/trixie-20260713-slim/images/sha256-53dfdbcd6fbc78c5052f35d2a5c798259f4c615cd93582b4ff5ad4f04249c7e3
FROM docker.io/debian@sha256:020c0d20b9880058cbe785a9db107156c3c75c2ac944a6aa7ab59f2add76a7bd
USER root
SHELL ["/bin/bash", "-euo", "pipefail", "-c"]
ARG DEBIAN_FRONTEND=noninteractive
COPY ./apt-packages /tmp/apt-packages
RUN apt-get update -q \
&& xargs -a /tmp/apt-packages apt-get install -y --no-install-recommends -q \
&& apt-get upgrade -y -q curl libcap2 libcurl3t64-gnutls libcurl4t64 \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* /tmp/apt-packages
ARG MISE_VERSION=v2026.7.3
ARG MISE_HTTP_TIMEOUT=60
ARG MISE_HTTP_RETRIES=5
ARG MISE_VERBOSE=true
ARG MISE_JOBS=4
COPY --chown=root:root --chmod=644 ./mise.toml /etc/mise/config.toml
RUN --mount=type=cache,id=mise-downloads,target=/root/.local/share/mise,sharing=locked \
--mount=type=secret,id=github_token,env=GITHUB_TOKEN,required=true \
curl -fsSL https://mise.run \
| MISE_VERSION=${MISE_VERSION} MISE_INSTALL_PATH=/usr/local/bin/mise sh \
&& chmod 755 /etc/mise \
&& mise install --system --yes \
&& ln -sf "$(mise where aqua:fish-shell/fish-shell)/fish" /usr/local/bin/fish \
&& echo /usr/local/bin/fish >> /etc/shells \
&& rm -f "$(mise where go)/src/crypto/x509/platform_root_key.pem" \
&& mise cache clear
# Build the Go-based CLIs from source with the Go 1.26.5 toolchain installed above,
# so their embedded stdlib (and golang.org/x/* deps) are patched. We do NOT pin
# these in mise.toml because the mise prebuilts ship stale Go and some (direnv,
# glow) have no newer release at all. Trivy scans the binaries on disk, so leaving
# the vulnerable mise copies around would keep the gate red — hence source builds.
# Why source-build and not `go install pkg@ver`: `go install` rebuilds the stdlib
# with the new Go but leaves each tool's PINNED golang.org/x/{sys,net,text,crypto}
# untouched, so those ship stale and trip Trivy (CVE-2026-39824/46600/56852, plus the
# older x/crypto HIGH in task). Each tool gets a throwaway module where we `go get`
# the tool, then bump the four x/* modules to fixed versions; `go build` only links
# the ones the tool actually imports. Fixes applied (all four x/* bumped to their
# coordinated latest; CVE fix thresholds are 0.44/0.56/0.39 and crypto>0.49, so the
# pinned set clears them. The x/* modules are a tightly-coupled dependency set and
# must be bumped together to a consistent graph — a partial bump fails go.mod
# resolution, e.g. x/net@v0.56 requires x/crypto@v0.53):
# direnv/lazygit/fzf/shfmt : golang.org/x/sys -> v0.47.0 (CVE-2026-39824)
# glow/task : golang.org/x/net -> v0.57.0 (CVE-2026-46600), x/text -> v0.40.0 (CVE-2026-56852)
# lazygit/glow : golang.org/x/text -> v0.40.0 (CVE-2026-56852)
# task : golang.org/x/crypto -> v0.54.0 (older x/crypto HIGH)
# task : google.golang.org/grpc -> v1.82.1 (GHSA-hrxh-6v49-42gf);
# bumped inline (not in XSYS) since only task imports grpc.
# shfmt: latest tag (v3.13.1) has NO newer release, so source-rebuild is the only
# fix. The Mason prebuilt installed later by nvim is overwritten in a post-step.
# DL3062 false positive: hadolint mis-parses `go -C <dir> get pkg@ver` and reports
# it unpinned, but every go get below IS pinned with @<version>.
# hadolint ignore=DL3062
RUN --mount=type=cache,id=go-build,target=/root/.cache/go-build,sharing=locked \
--mount=type=cache,id=go-mod,target=/root/go/pkg/mod,sharing=locked \
eval "$(mise hook-env)" && \
export GOPATH=/root/go GOBIN=/usr/local/bin \
GOCACHE=/root/.cache/go-build GOMODCACHE=/root/go/pkg/mod && \
go version && \
XSYS=(golang.org/x/sys@v0.47.0 golang.org/x/net@v0.57.0 golang.org/x/text@v0.40.0 golang.org/x/crypto@v0.54.0) && \
rm -rf /tmp/direnv && mkdir -p /tmp/direnv && \
go -C /tmp/direnv mod init direnv && \
go -C /tmp/direnv get github.com/direnv/direnv/v2@v2.37.1 && \
go -C /tmp/direnv get "${XSYS[@]}" && \
go -C /tmp/direnv build -o /usr/local/bin/direnv github.com/direnv/direnv/v2 && \
rm -rf /tmp/direnv && \
rm -rf /tmp/lazygit && mkdir -p /tmp/lazygit && \
go -C /tmp/lazygit mod init lazygit && \
go -C /tmp/lazygit get github.com/jesseduffield/lazygit@v0.63.1 && \
go -C /tmp/lazygit get "${XSYS[@]}" && \
go -C /tmp/lazygit build -o /usr/local/bin/lazygit github.com/jesseduffield/lazygit && \
rm -rf /tmp/lazygit && \
rm -rf /tmp/fzf && mkdir -p /tmp/fzf && \
go -C /tmp/fzf mod init fzf && \
go -C /tmp/fzf get github.com/junegunn/fzf@v0.74.0 && \
go -C /tmp/fzf get "${XSYS[@]}" && \
go -C /tmp/fzf build -o /usr/local/bin/fzf github.com/junegunn/fzf && \
rm -rf /tmp/fzf && \
rm -rf /tmp/shfmt && mkdir -p /tmp/shfmt && \
go -C /tmp/shfmt mod init shfmt && \
go -C /tmp/shfmt get mvdan.cc/sh/v3/cmd/shfmt@v3.13.1 && \
go -C /tmp/shfmt get "${XSYS[@]}" && \
go -C /tmp/shfmt build -o /usr/local/bin/shfmt mvdan.cc/sh/v3/cmd/shfmt && \
rm -rf /tmp/shfmt && \
# glow v2: NOTE the /v2 module path (v1 is a different, older major).
rm -rf /tmp/glow && mkdir -p /tmp/glow && \
go -C /tmp/glow mod init glow && \
go -C /tmp/glow get github.com/charmbracelet/glow/v2@v2.1.2 && \
go -C /tmp/glow get "${XSYS[@]}" && \
go -C /tmp/glow build -o /usr/local/bin/glow github.com/charmbracelet/glow/v2 && \
rm -rf /tmp/glow && \
rm -rf /tmp/task && mkdir -p /tmp/task && \
go -C /tmp/task mod init task && \
go -C /tmp/task get github.com/go-task/task/v3/cmd/task@v3.52.0 && \
go -C /tmp/task get "${XSYS[@]}" google.golang.org/grpc@v1.82.1 && \
go -C /tmp/task build -o /usr/local/bin/task github.com/go-task/task/v3/cmd/task && \
rm -rf /tmp/task
# Post-install patch: replace npm's bundled undici (6.26.0, CVE-2026-12151 HIGH),
# tar (7.5.16, CVE-2026-59873 CRITICAL + CVE-2026-59874 HIGH + GHSA-r292-9mhp-454m
# MEDIUM in <=7.5.20) and brace-expansion (5.0.6, CVE-2026-13149 HIGH) with fixed,
# same-major drop-ins (undici 6.27.0, tar 7.5.22, brace-expansion 5.0.8). Node's bundled npm deps are NOT updated by
# Node minor bumps (26.3.1/26.4.0/26.5.0 all still ship the old versions), so patch
# in place. (The Go test-fixture PEM is deleted in the mise-install RUN above,
# in the same layer it's created in — deleting it in a later layer wouldn't clear it
# from the earlier layer diff that Trivy scans.)
RUN NODE_INSTALL="$(mise where node)" && \
NM="$NODE_INSTALL/lib/node_modules/npm/node_modules" && \
rm -rf "$NM/undici" && \
curl -fsSL https://registry.npmjs.org/undici/-/undici-6.27.0.tgz | tar xz -C "$NM" && \
mv "$NM/package" "$NM/undici" && \
grep -q '"version": "6.27.0"' "$NM/undici/package.json" && \
rm -rf "$NM/tar" && \
curl -fsSL https://registry.npmjs.org/tar/-/tar-7.5.22.tgz | tar xz -C "$NM" && \
mv "$NM/package" "$NM/tar" && \
grep -q '"version": "7.5.22"' "$NM/tar/package.json" && \
rm -rf "$NM/brace-expansion" && \
curl -fsSL https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.8.tgz | tar xz -C "$NM" && \
mv "$NM/package" "$NM/brace-expansion" && \
grep -q '"version": "5.0.8"' "$NM/brace-expansion/package.json"
ARG USER_ID=1000
ARG GROUP_ID=1000
ARG USERNAME=devel
RUN groupadd -g ${GROUP_ID} ${USERNAME} \
&& useradd -l -m -u ${USER_ID} -g ${GROUP_ID} -G sudo -s /usr/local/bin/fish ${USERNAME} \
&& echo "${USERNAME} ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/${USERNAME} \
&& chmod 0440 /etc/sudoers.d/${USERNAME} \
&& rm -f /var/log/lastlog /var/log/faillog
ENV HOME=/home/${USERNAME}
ENV DOTFILES_DIR=${HOME}/dotfiles
ENV TERM=xterm-256color
# Explicit override that tells nvim to access system clipboard via OSC52 excape sequence.
# It would work only in modern terminals such as iTerm2, WezTerm, Alacritty, Kitty, Ghostty, Windows Terminal, etc.
ENV NVIM_CLIPBOARD=osc52
USER ${USERNAME}
ARG DOTFILES_REPO_URL=https://github.com/leonidgrishenkov/dotfiles.git
ARG XDG_DATA_HOME=${HOME}/.local/share
WORKDIR ${DOTFILES_DIR}
RUN git clone -q --depth=1 -b "main" --single-branch "${DOTFILES_REPO_URL}" "${DOTFILES_DIR}" \
&& eval "$(mise hook-env)" \
&& cat ./stow/linux-essential | xargs -I {} stow {} \
&& nvim --headless "+Lazy! restore" +qa \
&& pi install git:github.com/leonidgrishenkov/pi-extensions \
&& npx -y github:leonidgrishenkov/agent-skills install --target pi --target claude \
&& bat cache --build
# Overwrite Mason's prebuilt shfmt (built with Go 1.26.1, vuln stdlib) with the
# source-built copy from the Go step above (built with Go 1.26.5). Mason names the
# binary shfmt_v<ver>_linux_<arch> and symlinks bin/shfmt -> it; we swap the real
# file in place. No-op if Mason didn't install shfmt (find returns nothing).
RUN find "${HOME}/.local/share/nvim/mason/packages/shfmt" -type f -name 'shfmt_v*' \
-exec cp /usr/local/bin/shfmt {} \; 2>/dev/null || true
WORKDIR ${HOME}
SHELL ["/usr/local/bin/fish"]
CMD ["fish"]