@opencode-cloud/core 3.1.1 → 3.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Cargo.toml +1 -1
- package/README.md +33 -0
- package/package.json +1 -1
- package/src/config/schema.rs +14 -4
- package/src/docker/Dockerfile +342 -89
- package/src/docker/image.rs +415 -66
- package/src/docker/progress.rs +67 -67
package/Cargo.toml
CHANGED
package/README.md
CHANGED
|
@@ -129,6 +129,39 @@ occ uninstall
|
|
|
129
129
|
occ config show
|
|
130
130
|
```
|
|
131
131
|
|
|
132
|
+
## Authentication
|
|
133
|
+
|
|
134
|
+
opencode-cloud uses **PAM (Pluggable Authentication Modules)** for authentication. Users created via `occ user add` can authenticate to both:
|
|
135
|
+
- **opencode web UI** - Access the coding interface
|
|
136
|
+
- **Cockpit** - System administration interface
|
|
137
|
+
|
|
138
|
+
### Creating Users
|
|
139
|
+
|
|
140
|
+
Create a user with a password:
|
|
141
|
+
```bash
|
|
142
|
+
occ user add <username>
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Generate a random password:
|
|
146
|
+
```bash
|
|
147
|
+
occ user add <username> --generate
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Managing Users
|
|
151
|
+
|
|
152
|
+
- List users: `occ user list`
|
|
153
|
+
- Change password: `occ user passwd <username>`
|
|
154
|
+
- Remove user: `occ user remove <username>`
|
|
155
|
+
- Enable/disable account: `occ user enable <username>` / `occ user disable <username>`
|
|
156
|
+
|
|
157
|
+
### Legacy Authentication Fields
|
|
158
|
+
|
|
159
|
+
The `auth_username` and `auth_password` config fields are **deprecated** and ignored. They are kept in the config schema for backward compatibility with existing deployments, but new users should be created via `occ user add` instead.
|
|
160
|
+
|
|
161
|
+
To migrate from legacy fields:
|
|
162
|
+
1. Create a PAM user: `occ user add <username>`
|
|
163
|
+
2. The legacy fields will be automatically cleared on next config save
|
|
164
|
+
|
|
132
165
|
### Rebuilding the Docker Image
|
|
133
166
|
|
|
134
167
|
When developing locally or after updating opencode-cloud, you may need to rebuild the Docker image to pick up changes in the embedded Dockerfile:
|
package/package.json
CHANGED
package/src/config/schema.rs
CHANGED
|
@@ -42,11 +42,18 @@ pub struct Config {
|
|
|
42
42
|
#[serde(default = "default_restart_delay")]
|
|
43
43
|
pub restart_delay: u32,
|
|
44
44
|
|
|
45
|
-
/// Username for opencode basic auth (
|
|
45
|
+
/// Username for opencode basic auth (DEPRECATED - use PAM users via `occ user add` instead)
|
|
46
|
+
///
|
|
47
|
+
/// This field is kept for backward compatibility but is ignored.
|
|
48
|
+
/// New deployments should create users via `occ user add` which uses PAM authentication.
|
|
49
|
+
/// Legacy deployments can migrate by running `occ user add <username>`.
|
|
46
50
|
#[serde(default)]
|
|
47
51
|
pub auth_username: Option<String>,
|
|
48
52
|
|
|
49
|
-
/// Password for opencode basic auth (
|
|
53
|
+
/// Password for opencode basic auth (DEPRECATED - use PAM users via `occ user add` instead)
|
|
54
|
+
///
|
|
55
|
+
/// This field is kept for backward compatibility but is ignored.
|
|
56
|
+
/// Passwords are stored in the container's /etc/shadow via PAM, not in config files.
|
|
50
57
|
#[serde(default)]
|
|
51
58
|
pub auth_password: Option<String>,
|
|
52
59
|
|
|
@@ -233,8 +240,11 @@ impl Config {
|
|
|
233
240
|
/// Check if required auth credentials are configured
|
|
234
241
|
///
|
|
235
242
|
/// Returns true if:
|
|
236
|
-
/// -
|
|
237
|
-
/// -
|
|
243
|
+
/// - The users array is non-empty (PAM-based auth - preferred), OR
|
|
244
|
+
/// - Both auth_username and auth_password are Some and non-empty (legacy - deprecated)
|
|
245
|
+
///
|
|
246
|
+
/// **Note:** Legacy auth_username/auth_password fields are deprecated and ignored in favor of PAM users.
|
|
247
|
+
/// This method still checks them for backward compatibility, but new deployments should use `occ user add`.
|
|
238
248
|
///
|
|
239
249
|
/// This is used to determine if the setup wizard needs to run.
|
|
240
250
|
pub fn has_required_auth(&self) -> bool {
|
package/src/docker/Dockerfile
CHANGED
|
@@ -40,7 +40,10 @@ ENV DEBIAN_FRONTEND=noninteractive
|
|
|
40
40
|
ENV TZ=UTC
|
|
41
41
|
|
|
42
42
|
# Install build essentials (2026-01-22)
|
|
43
|
-
|
|
43
|
+
# Use BuildKit cache mount for APT package lists and cache
|
|
44
|
+
RUN --mount=type=cache,target=/var/lib/apt/lists \
|
|
45
|
+
--mount=type=cache,target=/var/cache/apt \
|
|
46
|
+
apt-get update && apt-get install -y --no-install-recommends \
|
|
44
47
|
build-essential=12.* \
|
|
45
48
|
# UNPINNED: ca-certificates - security-critical root certs, needs auto-updates
|
|
46
49
|
ca-certificates \
|
|
@@ -74,7 +77,10 @@ ENV LC_ALL=C.UTF-8
|
|
|
74
77
|
# Install core system packages in logical groups for better caching
|
|
75
78
|
|
|
76
79
|
# Group 1: Core utilities and build tools (2026-01-22)
|
|
77
|
-
|
|
80
|
+
# Use BuildKit cache mount for APT package lists and cache
|
|
81
|
+
RUN --mount=type=cache,target=/var/lib/apt/lists \
|
|
82
|
+
--mount=type=cache,target=/var/cache/apt \
|
|
83
|
+
apt-get update && apt-get install -y --no-install-recommends \
|
|
78
84
|
# Init systems
|
|
79
85
|
tini=0.19.* \
|
|
80
86
|
dumb-init=1.2.* \
|
|
@@ -120,6 +126,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
|
120
126
|
netcat-openbsd=1.226-* \
|
|
121
127
|
iputils-ping=3:20240117-* \
|
|
122
128
|
dnsutils=1:9.18.* \
|
|
129
|
+
# Reverse proxy for opencode UI + API
|
|
130
|
+
nginx=1.24.* \
|
|
123
131
|
# Compression
|
|
124
132
|
zip=3.0-* \
|
|
125
133
|
unzip=6.0-* \
|
|
@@ -136,14 +144,20 @@ RUN systemctl mask \
|
|
|
136
144
|
systemd-remount-fs.service
|
|
137
145
|
|
|
138
146
|
# Group 2: Database clients (2026-01-22)
|
|
139
|
-
|
|
147
|
+
# Use BuildKit cache mount for APT package lists and cache
|
|
148
|
+
RUN --mount=type=cache,target=/var/lib/apt/lists \
|
|
149
|
+
--mount=type=cache,target=/var/cache/apt \
|
|
150
|
+
apt-get update && apt-get install -y --no-install-recommends \
|
|
140
151
|
sqlite3=3.45.* \
|
|
141
152
|
postgresql-client=16+* \
|
|
142
153
|
default-mysql-client=1.1.* \
|
|
143
154
|
&& rm -rf /var/lib/apt/lists/*
|
|
144
155
|
|
|
145
156
|
# Group 3: Development libraries for compiling tools (2026-01-22)
|
|
146
|
-
|
|
157
|
+
# Use BuildKit cache mount for APT package lists and cache
|
|
158
|
+
RUN --mount=type=cache,target=/var/lib/apt/lists \
|
|
159
|
+
--mount=type=cache,target=/var/cache/apt \
|
|
160
|
+
apt-get update && apt-get install -y --no-install-recommends \
|
|
147
161
|
libssl-dev=3.0.* \
|
|
148
162
|
libffi-dev=3.4.* \
|
|
149
163
|
zlib1g-dev=1:1.3.* \
|
|
@@ -151,6 +165,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
|
151
165
|
libreadline-dev=8.2-* \
|
|
152
166
|
libsqlite3-dev=3.45.* \
|
|
153
167
|
libncurses-dev=6.4+* \
|
|
168
|
+
libpam0g-dev=1.5.* \
|
|
154
169
|
liblzma-dev=5.6.* \
|
|
155
170
|
&& rm -rf /var/lib/apt/lists/*
|
|
156
171
|
|
|
@@ -221,6 +236,7 @@ ENV PATH="/home/opencode/.local/share/mise/shims:${PATH}"
|
|
|
221
236
|
# Uses stable toolchain (rustup manages toolchain versioning)
|
|
222
237
|
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable \
|
|
223
238
|
&& . /home/opencode/.cargo/env \
|
|
239
|
+
&& rustup default stable \
|
|
224
240
|
&& rustup component add rust-analyzer rustfmt clippy
|
|
225
241
|
|
|
226
242
|
ENV PATH="/home/opencode/.cargo/bin:${PATH}"
|
|
@@ -241,15 +257,20 @@ ENV PNPM_HOME="/home/opencode/.local/share/pnpm"
|
|
|
241
257
|
ENV PATH="${PNPM_HOME}:${PATH}"
|
|
242
258
|
RUN mkdir -p "${PNPM_HOME}"
|
|
243
259
|
|
|
260
|
+
|
|
244
261
|
# uv - self-managing installer, trusted to handle versions (fast Python package manager)
|
|
245
262
|
RUN curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
246
263
|
|
|
247
264
|
# Install pipx for isolated Python application installs
|
|
248
|
-
|
|
265
|
+
# Use BuildKit cache mount for pip cache
|
|
266
|
+
RUN --mount=type=cache,target=/home/opencode/.cache/pip,uid=1000,gid=1000,mode=0755 \
|
|
267
|
+
mkdir -p /home/opencode/.cache/pip \
|
|
268
|
+
&& eval "$(/home/opencode/.local/bin/mise activate bash)" \
|
|
249
269
|
&& pip install --user pipx \
|
|
250
270
|
&& pipx ensurepath
|
|
251
271
|
|
|
252
272
|
# Install global TypeScript compiler
|
|
273
|
+
# NOTE: Avoid cache mount here to prevent pnpm store permission issues
|
|
253
274
|
RUN eval "$(/home/opencode/.local/bin/mise activate bash)" \
|
|
254
275
|
&& pnpm add -g typescript
|
|
255
276
|
|
|
@@ -258,7 +279,9 @@ RUN eval "$(/home/opencode/.local/bin/mise activate bash)" \
|
|
|
258
279
|
# -----------------------------------------------------------------------------
|
|
259
280
|
# ripgrep 15.1.0 - fast regex search
|
|
260
281
|
# eza 0.23.4 - modern ls replacement
|
|
261
|
-
|
|
282
|
+
# NOTE: Avoid cache mounts here due to permission issues with non-root Cargo cache
|
|
283
|
+
RUN mkdir -p /home/opencode/.cargo/registry /home/opencode/.cargo/git \
|
|
284
|
+
&& . /home/opencode/.cargo/env \
|
|
262
285
|
&& cargo install --locked ripgrep@15.1.0 eza@0.23.4
|
|
263
286
|
|
|
264
287
|
# lazygit v0.58.1 (2026-01-12) - terminal UI for git
|
|
@@ -304,8 +327,11 @@ RUN . /home/opencode/.cargo/env \
|
|
|
304
327
|
# && go install mvdan.cc/sh/v3/cmd/shfmt@v3.12.0
|
|
305
328
|
|
|
306
329
|
# Install btop system monitor (2026-01-22)
|
|
330
|
+
# Use BuildKit cache mount for APT package lists and cache
|
|
307
331
|
USER root
|
|
308
|
-
RUN
|
|
332
|
+
RUN --mount=type=cache,target=/var/lib/apt/lists \
|
|
333
|
+
--mount=type=cache,target=/var/cache/apt \
|
|
334
|
+
apt-get update && apt-get install -y --no-install-recommends btop=1.3.* \
|
|
309
335
|
&& rm -rf /var/lib/apt/lists/*
|
|
310
336
|
USER opencode
|
|
311
337
|
|
|
@@ -313,7 +339,10 @@ USER opencode
|
|
|
313
339
|
# GitHub CLI
|
|
314
340
|
# -----------------------------------------------------------------------------
|
|
315
341
|
USER root
|
|
316
|
-
|
|
342
|
+
# Use BuildKit cache mount for APT package lists and cache
|
|
343
|
+
RUN --mount=type=cache,target=/var/lib/apt/lists \
|
|
344
|
+
--mount=type=cache,target=/var/cache/apt \
|
|
345
|
+
curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg \
|
|
317
346
|
&& chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg \
|
|
318
347
|
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" > /etc/apt/sources.list.d/github-cli.list \
|
|
319
348
|
&& apt-get update && apt-get install -y --no-install-recommends gh \
|
|
@@ -321,38 +350,41 @@ RUN curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | d
|
|
|
321
350
|
USER opencode
|
|
322
351
|
|
|
323
352
|
# -----------------------------------------------------------------------------
|
|
324
|
-
# Cockpit Web Console (2026-01-22)
|
|
353
|
+
# Cockpit Web Console (2026-01-22) - temporarily disabled
|
|
325
354
|
# -----------------------------------------------------------------------------
|
|
326
355
|
# Cockpit provides web-based administration for the container
|
|
327
356
|
# Ubuntu noble has cockpit 316 in main repos
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
357
|
+
# Use BuildKit cache mount for APT package lists and cache
|
|
358
|
+
# USER root
|
|
359
|
+
# RUN --mount=type=cache,target=/var/lib/apt/lists \
|
|
360
|
+
# --mount=type=cache,target=/var/cache/apt \
|
|
361
|
+
# apt-get update && \
|
|
362
|
+
# apt-get install -y --no-install-recommends \
|
|
363
|
+
# cockpit-ws \
|
|
364
|
+
# cockpit-system \
|
|
365
|
+
# cockpit-bridge \
|
|
366
|
+
# && rm -rf /var/lib/apt/lists/*
|
|
367
|
+
#
|
|
336
368
|
# Enable Cockpit socket activation (manual symlink since systemctl doesn't work during build)
|
|
337
|
-
RUN mkdir -p /etc/systemd/system/sockets.target.wants \
|
|
338
|
-
|
|
339
|
-
|
|
369
|
+
# RUN mkdir -p /etc/systemd/system/sockets.target.wants \
|
|
370
|
+
# && ln -sf /lib/systemd/system/cockpit.socket /etc/systemd/system/sockets.target.wants/cockpit.socket
|
|
371
|
+
#
|
|
340
372
|
# Configure Cockpit for HTTP (TLS terminated externally) and proxy headers
|
|
341
|
-
RUN mkdir -p /etc/cockpit && \
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
USER opencode
|
|
373
|
+
# RUN mkdir -p /etc/cockpit && \
|
|
374
|
+
# printf '%s\n' \
|
|
375
|
+
# '[WebService]' \
|
|
376
|
+
# '# Allow HTTP connections (TLS terminated externally like opencode)' \
|
|
377
|
+
# 'AllowUnencrypted = true' \
|
|
378
|
+
# '' \
|
|
379
|
+
# '# Trust proxy headers for X-Forwarded-For, X-Forwarded-Proto' \
|
|
380
|
+
# 'ProtocolHeader = X-Forwarded-Proto' \
|
|
381
|
+
# 'ForwardedForHeader = X-Forwarded-For' \
|
|
382
|
+
# '' \
|
|
383
|
+
# '# Limit concurrent login attempts' \
|
|
384
|
+
# 'MaxStartups = 10' \
|
|
385
|
+
# > /etc/cockpit/cockpit.conf
|
|
386
|
+
#
|
|
387
|
+
# USER opencode
|
|
356
388
|
|
|
357
389
|
# -----------------------------------------------------------------------------
|
|
358
390
|
# CI/CD + tooling (disabled)
|
|
@@ -416,59 +448,6 @@ USER opencode
|
|
|
416
448
|
# RUN eval "$(/home/opencode/.local/bin/mise activate bash)" \
|
|
417
449
|
# && go install github.com/fullstorydev/grpcurl/cmd/grpcurl@v1.9.3
|
|
418
450
|
|
|
419
|
-
# -----------------------------------------------------------------------------
|
|
420
|
-
# opencode Installation
|
|
421
|
-
# -----------------------------------------------------------------------------
|
|
422
|
-
# opencode - self-managing installer, trusted to handle versions
|
|
423
|
-
# The script installs to ~/.opencode/bin/
|
|
424
|
-
# Retry logic added because opencode.ai API can be flaky during parallel builds
|
|
425
|
-
RUN for i in 1 2 3 4 5; do \
|
|
426
|
-
curl -fsSL https://opencode.ai/install | bash && break || \
|
|
427
|
-
echo "Attempt $i failed, retrying in 10s..." && sleep 10; \
|
|
428
|
-
done \
|
|
429
|
-
&& ls -la /home/opencode/.opencode/bin/opencode \
|
|
430
|
-
&& /home/opencode/.opencode/bin/opencode --version
|
|
431
|
-
|
|
432
|
-
# Add opencode to PATH
|
|
433
|
-
ENV PATH="/home/opencode/.opencode/bin:${PATH}"
|
|
434
|
-
|
|
435
|
-
# -----------------------------------------------------------------------------
|
|
436
|
-
# GSD Plugin Installation
|
|
437
|
-
# -----------------------------------------------------------------------------
|
|
438
|
-
# Install the GSD (Get Shit Done) plugin for opencode
|
|
439
|
-
# Note: If this fails in container builds due to "~" path resolution, retry with
|
|
440
|
-
# OPENCODE_CONFIG_DIR=/home/opencode/.config/opencode set explicitly.
|
|
441
|
-
RUN npx --yes get-shit-done-cc --opencode --global
|
|
442
|
-
|
|
443
|
-
# -----------------------------------------------------------------------------
|
|
444
|
-
# opencode systemd Service (2026-01-22)
|
|
445
|
-
# -----------------------------------------------------------------------------
|
|
446
|
-
# Create opencode as a systemd service for Cockpit integration
|
|
447
|
-
USER root
|
|
448
|
-
RUN printf '%s\n' \
|
|
449
|
-
'[Unit]' \
|
|
450
|
-
'Description=opencode Web Interface' \
|
|
451
|
-
'After=network.target' \
|
|
452
|
-
'' \
|
|
453
|
-
'[Service]' \
|
|
454
|
-
'Type=simple' \
|
|
455
|
-
'User=opencode' \
|
|
456
|
-
'WorkingDirectory=/home/opencode/workspace' \
|
|
457
|
-
'ExecStart=/home/opencode/.opencode/bin/opencode web --port 3000 --hostname 0.0.0.0' \
|
|
458
|
-
'Restart=always' \
|
|
459
|
-
'RestartSec=5' \
|
|
460
|
-
'Environment=PATH=/home/opencode/.opencode/bin:/home/opencode/.local/bin:/home/opencode/.cargo/bin:/home/opencode/.local/share/mise/shims:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin' \
|
|
461
|
-
'' \
|
|
462
|
-
'[Install]' \
|
|
463
|
-
'WantedBy=multi-user.target' \
|
|
464
|
-
> /etc/systemd/system/opencode.service
|
|
465
|
-
|
|
466
|
-
# Enable opencode service to start at boot (manual symlink since systemctl doesn't work during build)
|
|
467
|
-
RUN mkdir -p /etc/systemd/system/multi-user.target.wants \
|
|
468
|
-
&& ln -sf /etc/systemd/system/opencode.service /etc/systemd/system/multi-user.target.wants/opencode.service
|
|
469
|
-
|
|
470
|
-
USER opencode
|
|
471
|
-
|
|
472
451
|
# -----------------------------------------------------------------------------
|
|
473
452
|
# Sensible Defaults Configuration
|
|
474
453
|
# -----------------------------------------------------------------------------
|
|
@@ -536,6 +515,279 @@ RUN printf '%s\n' \
|
|
|
536
515
|
# Set up pipx path
|
|
537
516
|
RUN echo 'export PATH="/home/opencode/.local/bin:$PATH"' >> /home/opencode/.zshrc
|
|
538
517
|
|
|
518
|
+
# -----------------------------------------------------------------------------
|
|
519
|
+
# opencode Setup (Fork + Broker + Proxy)
|
|
520
|
+
# -----------------------------------------------------------------------------
|
|
521
|
+
# Keep this block near the end to preserve cache for earlier layers. We expect
|
|
522
|
+
# opencode fork changes to happen more often than base tooling changes.
|
|
523
|
+
#
|
|
524
|
+
# This block includes:
|
|
525
|
+
# - opencode build (backend binary) + app build (frontend dist)
|
|
526
|
+
# - opencode-broker build
|
|
527
|
+
# - nginx config for single-endpoint UI + API proxy
|
|
528
|
+
# - PAM configuration + systemd services
|
|
529
|
+
# - opencode config file
|
|
530
|
+
#
|
|
531
|
+
# NOTE: This section switches between opencode and root users as needed.
|
|
532
|
+
|
|
533
|
+
# -----------------------------------------------------------------------------
|
|
534
|
+
# opencode Installation (Fork from pRizz/opencode)
|
|
535
|
+
# -----------------------------------------------------------------------------
|
|
536
|
+
# Clone the fork and build opencode from source (as non-root user)
|
|
537
|
+
# Pin to specific commit for reproducibility: 50fd5d1a6a17dc1b378a0e60b464a75dd876d6e2
|
|
538
|
+
# Build opencode from source (BuildKit cache mounts disabled for now)
|
|
539
|
+
RUN rm -rf /tmp/opencode-repo \
|
|
540
|
+
&& git clone --depth 1 https://github.com/pRizz/opencode.git /tmp/opencode-repo \
|
|
541
|
+
&& cd /tmp/opencode-repo \
|
|
542
|
+
&& git checkout 50fd5d1a6a17dc1b378a0e60b464a75dd876d6e2 \
|
|
543
|
+
&& curl -fsSL https://bun.sh/install | bash -s "bun-v1.3.5" \
|
|
544
|
+
&& export PATH="/home/opencode/.bun/bin:${PATH}" \
|
|
545
|
+
&& bun install --frozen-lockfile \
|
|
546
|
+
&& bun run packages/opencode/script/build.ts --single \
|
|
547
|
+
&& cd packages/app \
|
|
548
|
+
&& bun run build \
|
|
549
|
+
&& cd /tmp/opencode-repo \
|
|
550
|
+
&& mkdir -p /home/opencode/.local/share/opencode/bin \
|
|
551
|
+
&& cp /tmp/opencode-repo/packages/opencode/dist/opencode-*/bin/opencode /home/opencode/.local/share/opencode/bin/opencode \
|
|
552
|
+
&& chown -R opencode:opencode /home/opencode/.local/share/opencode \
|
|
553
|
+
&& chmod +x /home/opencode/.local/share/opencode/bin/opencode \
|
|
554
|
+
&& /home/opencode/.local/share/opencode/bin/opencode --version
|
|
555
|
+
|
|
556
|
+
# Add opencode to PATH
|
|
557
|
+
ENV PATH="/home/opencode/.local/share/opencode/bin:${PATH}"
|
|
558
|
+
|
|
559
|
+
# Copy UI assets to standard web root (requires root)
|
|
560
|
+
USER root
|
|
561
|
+
RUN mkdir -p /var/www/opencode \
|
|
562
|
+
&& cp -R /tmp/opencode-repo/packages/app/dist/. /var/www/opencode/ \
|
|
563
|
+
&& chown -R root:root /var/www/opencode \
|
|
564
|
+
&& chmod 755 /var/www /var/www/opencode \
|
|
565
|
+
&& chmod -R a+rX /var/www/opencode
|
|
566
|
+
|
|
567
|
+
# -----------------------------------------------------------------------------
|
|
568
|
+
# opencode-broker Installation
|
|
569
|
+
# -----------------------------------------------------------------------------
|
|
570
|
+
# Build opencode-broker from source (Rust service for PAM authentication)
|
|
571
|
+
# The broker handles PAM authentication and user process spawning
|
|
572
|
+
# NOTE: Requires root privileges for setuid bit (chmod 4755) to allow broker
|
|
573
|
+
# to run with elevated privileges for PAM authentication
|
|
574
|
+
USER root
|
|
575
|
+
RUN cd /tmp/opencode-repo/packages/opencode-broker \
|
|
576
|
+
&& runuser -u opencode -- bash -c '. /home/opencode/.cargo/env && cargo build --release' \
|
|
577
|
+
&& mkdir -p /usr/local/bin \
|
|
578
|
+
&& cp target/release/opencode-broker /usr/local/bin/opencode-broker \
|
|
579
|
+
&& chmod 4755 /usr/local/bin/opencode-broker \
|
|
580
|
+
&& rm -rf /tmp/opencode-repo
|
|
581
|
+
|
|
582
|
+
# Verify broker binary exists and is executable
|
|
583
|
+
RUN ls -la /usr/local/bin/opencode-broker \
|
|
584
|
+
&& test -x /usr/local/bin/opencode-broker \
|
|
585
|
+
&& echo "Broker installed"
|
|
586
|
+
|
|
587
|
+
# -----------------------------------------------------------------------------
|
|
588
|
+
# Nginx Reverse Proxy for UI + API
|
|
589
|
+
# -----------------------------------------------------------------------------
|
|
590
|
+
# Serve the built UI from /var/www/opencode and proxy API/WebSocket
|
|
591
|
+
# TODO: Explore a sustainable routing strategy (e.g., backend-driven base URL or
|
|
592
|
+
# TODO: content-type aware proxying without hardcoded path lists).
|
|
593
|
+
RUN rm -f /etc/nginx/sites-enabled/default /etc/nginx/conf.d/default.conf 2>/dev/null || true \
|
|
594
|
+
&& printf '%s\n' \
|
|
595
|
+
'server {' \
|
|
596
|
+
' listen 3000;' \
|
|
597
|
+
' server_name _;' \
|
|
598
|
+
'' \
|
|
599
|
+
' root /var/www/opencode;' \
|
|
600
|
+
' index index.html;' \
|
|
601
|
+
'' \
|
|
602
|
+
' location = /health {' \
|
|
603
|
+
' proxy_pass http://127.0.0.1:3001;' \
|
|
604
|
+
' }' \
|
|
605
|
+
'' \
|
|
606
|
+
' location /assets/ {' \
|
|
607
|
+
' try_files $uri =404;' \
|
|
608
|
+
' }' \
|
|
609
|
+
'' \
|
|
610
|
+
' location ~* \.(?:js|css|png|jpg|jpeg|gif|svg|ico|webp|woff2?|ttf|map)$ {' \
|
|
611
|
+
' try_files $uri =404;' \
|
|
612
|
+
' }' \
|
|
613
|
+
'' \
|
|
614
|
+
' location ~ ^/(auth|session|sessions|pty|event|events|api|ws|v1|rpc|config|global|path|project|provider) {' \
|
|
615
|
+
' proxy_pass http://127.0.0.1:3001;' \
|
|
616
|
+
' proxy_http_version 1.1;' \
|
|
617
|
+
' proxy_set_header Upgrade $http_upgrade;' \
|
|
618
|
+
' proxy_set_header Connection "upgrade";' \
|
|
619
|
+
' proxy_set_header Host $host;' \
|
|
620
|
+
' proxy_set_header X-Real-IP $remote_addr;' \
|
|
621
|
+
' proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;' \
|
|
622
|
+
' proxy_set_header X-Forwarded-Proto $scheme;' \
|
|
623
|
+
' }' \
|
|
624
|
+
'' \
|
|
625
|
+
' location / {' \
|
|
626
|
+
' try_files $uri $uri/ @opencode_fallback;' \
|
|
627
|
+
' }' \
|
|
628
|
+
'' \
|
|
629
|
+
' location @opencode_fallback {' \
|
|
630
|
+
' if ($http_accept ~* "text/html") { rewrite ^ /index.html break; }' \
|
|
631
|
+
' proxy_pass http://127.0.0.1:3001;' \
|
|
632
|
+
' proxy_http_version 1.1;' \
|
|
633
|
+
' proxy_set_header Upgrade $http_upgrade;' \
|
|
634
|
+
' proxy_set_header Connection "upgrade";' \
|
|
635
|
+
' proxy_set_header Host $host;' \
|
|
636
|
+
' proxy_set_header X-Real-IP $remote_addr;' \
|
|
637
|
+
' proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;' \
|
|
638
|
+
' proxy_set_header X-Forwarded-Proto $scheme;' \
|
|
639
|
+
' }' \
|
|
640
|
+
'}' \
|
|
641
|
+
> /etc/nginx/conf.d/opencode.conf
|
|
642
|
+
|
|
643
|
+
# -----------------------------------------------------------------------------
|
|
644
|
+
# PAM Configuration
|
|
645
|
+
# -----------------------------------------------------------------------------
|
|
646
|
+
# Install PAM configuration for opencode authentication
|
|
647
|
+
# This allows opencode to authenticate users via PAM (same users as Cockpit)
|
|
648
|
+
# NOTE: Requires root privileges to write to /etc/pam.d/
|
|
649
|
+
RUN printf '%s\n' \
|
|
650
|
+
'# PAM configuration for OpenCode authentication' \
|
|
651
|
+
'# Install to /etc/pam.d/opencode' \
|
|
652
|
+
'' \
|
|
653
|
+
'# Standard UNIX authentication' \
|
|
654
|
+
'auth required pam_unix.so' \
|
|
655
|
+
'account required pam_unix.so' \
|
|
656
|
+
'' \
|
|
657
|
+
'# Optional: Enable TOTP 2FA (uncomment when pam_google_authenticator is installed)' \
|
|
658
|
+
'# auth required pam_google_authenticator.so' \
|
|
659
|
+
> /etc/pam.d/opencode \
|
|
660
|
+
&& chmod 644 /etc/pam.d/opencode
|
|
661
|
+
|
|
662
|
+
# Verify PAM config file exists
|
|
663
|
+
RUN ls -la /etc/pam.d/opencode && cat /etc/pam.d/opencode
|
|
664
|
+
|
|
665
|
+
# -----------------------------------------------------------------------------
|
|
666
|
+
# opencode-broker systemd Service
|
|
667
|
+
# -----------------------------------------------------------------------------
|
|
668
|
+
# Create opencode-broker service for PAM authentication
|
|
669
|
+
# NOTE: Requires root privileges to write to /etc/systemd/system/
|
|
670
|
+
RUN printf '%s\n' \
|
|
671
|
+
'[Unit]' \
|
|
672
|
+
'Description=OpenCode Authentication Broker' \
|
|
673
|
+
'Documentation=https://github.com/pRizz/opencode' \
|
|
674
|
+
'After=network.target' \
|
|
675
|
+
'' \
|
|
676
|
+
'[Service]' \
|
|
677
|
+
'Type=notify' \
|
|
678
|
+
'ExecStart=/usr/local/bin/opencode-broker' \
|
|
679
|
+
'ExecReload=/bin/kill -HUP $MAINPID' \
|
|
680
|
+
'Restart=always' \
|
|
681
|
+
'RestartSec=5' \
|
|
682
|
+
'' \
|
|
683
|
+
'# Security hardening' \
|
|
684
|
+
'NoNewPrivileges=false' \
|
|
685
|
+
'ProtectSystem=strict' \
|
|
686
|
+
'ProtectHome=read-only' \
|
|
687
|
+
'PrivateTmp=true' \
|
|
688
|
+
'ReadWritePaths=/run/opencode' \
|
|
689
|
+
'' \
|
|
690
|
+
'# Socket directory' \
|
|
691
|
+
'RuntimeDirectory=opencode' \
|
|
692
|
+
'RuntimeDirectoryMode=0755' \
|
|
693
|
+
'' \
|
|
694
|
+
'# Logging' \
|
|
695
|
+
'StandardOutput=journal' \
|
|
696
|
+
'StandardError=journal' \
|
|
697
|
+
'SyslogIdentifier=opencode-broker' \
|
|
698
|
+
'' \
|
|
699
|
+
'[Install]' \
|
|
700
|
+
'WantedBy=multi-user.target' \
|
|
701
|
+
> /etc/systemd/system/opencode-broker.service
|
|
702
|
+
|
|
703
|
+
# Enable opencode-broker service
|
|
704
|
+
RUN mkdir -p /etc/systemd/system/multi-user.target.wants \
|
|
705
|
+
&& ln -sf /etc/systemd/system/opencode-broker.service /etc/systemd/system/multi-user.target.wants/opencode-broker.service
|
|
706
|
+
|
|
707
|
+
USER opencode
|
|
708
|
+
|
|
709
|
+
# -----------------------------------------------------------------------------
|
|
710
|
+
# GSD Plugin Installation
|
|
711
|
+
# -----------------------------------------------------------------------------
|
|
712
|
+
# Install the GSD (Get Shit Done) plugin for opencode
|
|
713
|
+
# Note: If this fails in container builds due to "~" path resolution, retry with
|
|
714
|
+
# OPENCODE_CONFIG_DIR=/home/opencode/.config/opencode set explicitly.
|
|
715
|
+
RUN mkdir -p /home/opencode/.npm \
|
|
716
|
+
&& npx --yes get-shit-done-cc --opencode --global
|
|
717
|
+
|
|
718
|
+
# -----------------------------------------------------------------------------
|
|
719
|
+
# opencode systemd Service (2026-01-22)
|
|
720
|
+
# -----------------------------------------------------------------------------
|
|
721
|
+
# Create opencode as a systemd service for Cockpit integration (backend only)
|
|
722
|
+
# NOTE: Requires root privileges to write to /etc/systemd/system/
|
|
723
|
+
USER root
|
|
724
|
+
RUN printf '%s\n' \
|
|
725
|
+
'[Unit]' \
|
|
726
|
+
'Description=opencode Web Interface' \
|
|
727
|
+
'After=network.target opencode-broker.service' \
|
|
728
|
+
'' \
|
|
729
|
+
'[Service]' \
|
|
730
|
+
'Type=simple' \
|
|
731
|
+
'User=opencode' \
|
|
732
|
+
'WorkingDirectory=/home/opencode/workspace' \
|
|
733
|
+
'ExecStart=/home/opencode/.local/share/opencode/bin/opencode --port 3001 --hostname 0.0.0.0' \
|
|
734
|
+
'Restart=always' \
|
|
735
|
+
'RestartSec=5' \
|
|
736
|
+
'Environment=PATH=/home/opencode/.local/share/opencode/bin:/home/opencode/.local/bin:/home/opencode/.cargo/bin:/home/opencode/.local/share/mise/shims:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin' \
|
|
737
|
+
'' \
|
|
738
|
+
'[Install]' \
|
|
739
|
+
'WantedBy=multi-user.target' \
|
|
740
|
+
> /etc/systemd/system/opencode.service
|
|
741
|
+
|
|
742
|
+
# Enable opencode service to start at boot (manual symlink since systemctl doesn't work during build)
|
|
743
|
+
RUN mkdir -p /etc/systemd/system/multi-user.target.wants \
|
|
744
|
+
&& ln -sf /etc/systemd/system/opencode.service /etc/systemd/system/multi-user.target.wants/opencode.service
|
|
745
|
+
|
|
746
|
+
# Nginx service for serving UI + proxying API
|
|
747
|
+
RUN printf '%s\n' \
|
|
748
|
+
'[Unit]' \
|
|
749
|
+
'Description=Nginx reverse proxy for opencode UI' \
|
|
750
|
+
'After=network.target opencode.service' \
|
|
751
|
+
'' \
|
|
752
|
+
'[Service]' \
|
|
753
|
+
'Type=simple' \
|
|
754
|
+
'ExecStart=/usr/sbin/nginx -g "daemon off;"' \
|
|
755
|
+
'ExecReload=/usr/sbin/nginx -s reload' \
|
|
756
|
+
'Restart=always' \
|
|
757
|
+
'RestartSec=5' \
|
|
758
|
+
'' \
|
|
759
|
+
'[Install]' \
|
|
760
|
+
'WantedBy=multi-user.target' \
|
|
761
|
+
> /etc/systemd/system/opencode-nginx.service
|
|
762
|
+
|
|
763
|
+
# Enable nginx service
|
|
764
|
+
RUN mkdir -p /etc/systemd/system/multi-user.target.wants \
|
|
765
|
+
&& ln -sf /etc/systemd/system/opencode-nginx.service /etc/systemd/system/multi-user.target.wants/opencode-nginx.service
|
|
766
|
+
|
|
767
|
+
# Prevent the distro nginx service from also starting (port 3000 conflict)
|
|
768
|
+
RUN rm -f /etc/systemd/system/multi-user.target.wants/nginx.service \
|
|
769
|
+
&& ln -sf /dev/null /etc/systemd/system/nginx.service
|
|
770
|
+
|
|
771
|
+
# -----------------------------------------------------------------------------
|
|
772
|
+
# opencode Configuration
|
|
773
|
+
# -----------------------------------------------------------------------------
|
|
774
|
+
# Create opencode.json config file with PAM authentication enabled
|
|
775
|
+
RUN mkdir -p /home/opencode/.config/opencode \
|
|
776
|
+
&& printf '%s\n' \
|
|
777
|
+
'{' \
|
|
778
|
+
' "auth": {' \
|
|
779
|
+
' "enabled": true' \
|
|
780
|
+
' }' \
|
|
781
|
+
'}' \
|
|
782
|
+
> /home/opencode/.config/opencode/opencode.json \
|
|
783
|
+
&& chown -R opencode:opencode /home/opencode/.config/opencode \
|
|
784
|
+
&& chmod 644 /home/opencode/.config/opencode/opencode.json
|
|
785
|
+
|
|
786
|
+
# Verify config file exists
|
|
787
|
+
RUN ls -la /home/opencode/.config/opencode/opencode.json && cat /home/opencode/.config/opencode/opencode.json
|
|
788
|
+
|
|
789
|
+
USER opencode
|
|
790
|
+
|
|
539
791
|
# -----------------------------------------------------------------------------
|
|
540
792
|
# Entrypoint Script (Hybrid Init Support)
|
|
541
793
|
# -----------------------------------------------------------------------------
|
|
@@ -549,7 +801,8 @@ RUN printf '%s\n' \
|
|
|
549
801
|
' exec /sbin/init' \
|
|
550
802
|
'else' \
|
|
551
803
|
' # Use runuser to switch to opencode user without password prompt' \
|
|
552
|
-
'
|
|
804
|
+
' runuser -u opencode -- /home/opencode/.local/share/opencode/bin/opencode --port 3001 --hostname 0.0.0.0 &' \
|
|
805
|
+
' exec /usr/sbin/nginx -g "daemon off;"' \
|
|
553
806
|
'fi' \
|
|
554
807
|
> /usr/local/bin/entrypoint.sh && chmod +x /usr/local/bin/entrypoint.sh
|
|
555
808
|
|