Merge pull request #5207 from okxlin/deliver/opencode-1.18.4-20260727

Add OpenCode app
This commit is contained in:
okxlin
2026-07-28 10:38:46 +08:00
committed by GitHub
15 changed files with 450 additions and 0 deletions
+6
View File
@@ -0,0 +1,6 @@
CONTAINER_NAME=opencode-compose-check
PANEL_APP_PORT_HTTP=4096
APP_DATA_DIR=./data
OPENCODE_SERVER_USERNAME=opencode
OPENCODE_SERVER_PASSWORD=change-me-before-deploy
TZ=Asia/Shanghai
+86
View File
@@ -0,0 +1,86 @@
additionalProperties:
formFields:
- default: 4096
edit: true
envKey: PANEL_APP_PORT_HTTP
labelEn: Web Port
labelZh: Web 端口
label:
en: Web Port
zh: Web 端口
zh-Hant: Web 連接埠
ja: Web ポート
ko: 웹 포트
ru: Веб-порт
ms: Port Web
pt-br: Porta Web
required: true
rule: paramPort
type: number
- default: ./data
edit: true
envKey: APP_DATA_DIR
labelEn: Data Directory
labelZh: 数据目录
label:
en: Data Directory
zh: 数据目录
zh-Hant: 資料目錄
ja: データディレクトリ
ko: 데이터 디렉터리
ru: Каталог данных
ms: Direktori Data
pt-br: Diretório de Dados
required: true
type: text
- default: opencode
edit: true
envKey: OPENCODE_SERVER_USERNAME
labelEn: Server Username
labelZh: 服务器用户名
label:
en: Server Username
zh: 服务器用户名
zh-Hant: 伺服器使用者名稱
ja: サーバーユーザー名
ko: 서버 사용자 이름
ru: Имя пользователя сервера
ms: Nama Pengguna Pelayan
pt-br: Nome de Usuario do Servidor
required: true
rule: paramCommon
type: text
- default: ''
edit: true
envKey: OPENCODE_SERVER_PASSWORD
labelEn: Server Password
labelZh: 服务器密码
label:
en: Server Password
zh: 服务器密码
zh-Hant: 伺服器密碼
ja: サーバーパスワード
ko: 서버 비밀번호
ru: Пароль сервера
ms: Kata Laluan Pelayan
pt-br: Senha do Servidor
random: true
required: true
rule: paramComplexity
type: password
- default: Asia/Shanghai
edit: true
envKey: TZ
labelEn: Timezone
labelZh: 时区
label:
en: Timezone
zh: 时区
zh-Hant: 時區
ja: タイムゾーン
ko: 시간대
ru: Часовой пояс
ms: Zon Waktu
pt-br: Fuso Horário
required: true
type: text
+35
View File
@@ -0,0 +1,35 @@
services:
opencode:
image: "ghcr.io/anomalyco/opencode:1.18.7"
container_name: ${CONTAINER_NAME}
restart: unless-stopped
user: "1000:1000"
command: ["serve", "--hostname", "0.0.0.0", "--port", "4096"]
networks:
- 1panel-network
ports:
- "${PANEL_APP_PORT_HTTP}:4096"
volumes:
- "${APP_DATA_DIR}:/home/opencode"
environment:
- HOME=/home/opencode
- OPENCODE_SERVER_USERNAME=${OPENCODE_SERVER_USERNAME}
- OPENCODE_SERVER_PASSWORD=${OPENCODE_SERVER_PASSWORD}
- TZ=${TZ}
stop_grace_period: 15s
healthcheck:
test:
- CMD-SHELL
- >-
auth="$$(printf '%s:%s' "$${OPENCODE_SERVER_USERNAME}" "$${OPENCODE_SERVER_PASSWORD}" | base64 | tr -d '\n')";
wget -q -O /dev/null --header "Authorization: Basic $$auth" http://127.0.0.1:4096/global/health
interval: 1m
timeout: 5s
retries: 5
start_period: 20s
labels:
createdBy: "Apps"
networks:
1panel-network:
external: true
+37
View File
@@ -0,0 +1,37 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
ENV_FILE="${ENV_FILE:-$ROOT_DIR/.env}"
read_env_value() {
local value=""
[[ -f "$ENV_FILE" ]] || return 0
value="$(sed -n "s/^APP_DATA_DIR=//p" "$ENV_FILE" | tail -n 1)"
value="${value#\"}"
value="${value%\"}"
value="${value#\'}"
value="${value%\'}"
printf '%s\n' "$value"
}
data_dir_value="${APP_DATA_DIR:-$(read_env_value)}"
data_dir_value="${data_dir_value:-./data}"
data_dir_is_absolute=false
case "$data_dir_value" in
/) echo "refusing to use / as APP_DATA_DIR" >&2; exit 1 ;;
/*) data_dir="$data_dir_value"; data_dir_is_absolute=true ;;
*) data_dir="$ROOT_DIR/${data_dir_value#./}" ;;
esac
data_dir="$(readlink -f -- "$data_dir")"
case "$data_dir" in
/) echo "refusing to use / as APP_DATA_DIR" >&2; exit 1 ;;
esac
if [[ "$data_dir_is_absolute" == false && "$data_dir" != "$ROOT_DIR/"* ]]; then
echo "refusing relative APP_DATA_DIR outside the app directory" >&2
exit 1
fi
mkdir -p -- "$data_dir"
chown -R 1000:1000 -- "$data_dir"
@@ -0,0 +1,2 @@
#!/bin/bash
docker-compose down --volumes
+4
View File
@@ -0,0 +1,4 @@
#!/usr/bin/env bash
set -euo pipefail
exec "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/init.sh"
+79
View File
@@ -0,0 +1,79 @@
# OpenCode
## 产品介绍
OpenCode 是一个自托管 AI 编程助手,可通过浏览器管理 AI 编程会话。
## 主要功能
- 通过浏览器运行 OpenCode 的无头服务。
- 为服务配置独立的 HTTP Basic Auth 凭据。
- 在持久化数据目录中保存 OpenCode 状态。
## 访问说明
- 默认 Web 端口:`4096`
- 容器内部端口:`4096`
- 安装时必须设置服务器用户名和随机生成的密码。OpenCode 使用 HTTP Basic Auth 保护服务。
- 直接端口访问使用 HTTP;公开访问前请在 1Panel 中配置 HTTPS 反向代理。
## 数据与备份
- `Data Directory` 映射到容器的 `/home/opencode`,其中包含 OpenCode 配置、会话和已配置的模型提供商凭据。
- 升级或迁移前备份整个 `Data Directory`。
- 卸载会停止并移除容器,但不会删除数据目录。
## 安全边界
- 此包不挂载 Docker socket、宿主机工作区或其他宿主机敏感路径。
- 在 OpenCode 中配置的模型提供商凭据保存在持久化数据目录中;请将备份视为敏感数据。
## 版本
- `1.18.7` 固定到上游 OpenCode `v1.18.7` 镜像。
- `latest` 跟随上游 OpenCode 的最新镜像。
## 参考资料
- 上游仓库:<https://github.com/anomalyco/opencode>
- 官方文档:<https://opencode.ai/docs>
- 服务命令与认证实现:<https://github.com/anomalyco/opencode/blob/v1.18.7/packages/opencode/src/cli/cmd/serve.ts>
## Introduction
OpenCode is a self-hosted AI coding agent that manages AI-assisted coding sessions in the browser.
## Features
- Run OpenCode's headless service in the browser.
- Configure dedicated HTTP Basic Auth credentials for the service.
- Persist OpenCode state in a dedicated data directory.
## Access
- Default web port: `4096`
- Container port: `4096`
- Installation requires a server username and generated password. OpenCode protects the service with HTTP Basic Auth.
- Direct port access uses HTTP. Configure an HTTPS reverse proxy in 1Panel before public exposure.
## Data and Backup
- `Data Directory` maps to `/home/opencode` in the container and stores OpenCode configuration, sessions, and configured model-provider credentials.
- Back up the complete `Data Directory` before upgrades or migrations.
- Uninstall stops and removes the container but keeps the data directory.
## Security Boundary
- This package does not mount the Docker socket, a host workspace, or other sensitive host paths.
- Model-provider credentials configured in OpenCode live in the persistent data directory. Treat its backups as sensitive.
## Versions
- `1.18.7` is pinned to the upstream OpenCode `v1.18.7` image.
- `latest` follows the upstream OpenCode latest image.
## Sources
- Upstream repository: <https://github.com/anomalyco/opencode>
- Official documentation: <https://opencode.ai/docs>
- Serve command and authentication: <https://github.com/anomalyco/opencode/blob/v1.18.7/packages/opencode/src/cli/cmd/serve.ts>
+31
View File
@@ -0,0 +1,31 @@
name: OpenCode
tags:
- AI
title: 自托管 AI 编程助手
description: 自托管 AI 编程助手
additionalProperties:
key: opencode
name: OpenCode
tags:
- AI
shortDescZh: 自托管 AI 编程助手
shortDescEn: A self-hosted AI coding agent
description:
en: A self-hosted AI coding agent.
zh: 自托管 AI 编程助手。
zh-Hant: 自託管 AI 程式設計助理。
ja: セルフホスト型 AI コーディングエージェントです。
ko: 자체 호스팅 AI 코딩 에이전트입니다.
ru: Самостоятельно размещаемый ИИ-агент для программирования.
ms: Ejen pengekodan AI yang dihoskan sendiri.
pt-br: Agente de programacao por IA auto-hospedado.
type: tool
crossVersionUpdate: true
limit: 0
recommend: 0
website: https://opencode.ai/
document: https://opencode.ai/docs
github: https://github.com/anomalyco/opencode
architectures:
- amd64
- arm64
+6
View File
@@ -0,0 +1,6 @@
CONTAINER_NAME=opencode-compose-check
PANEL_APP_PORT_HTTP=4096
APP_DATA_DIR=./data
OPENCODE_SERVER_USERNAME=opencode
OPENCODE_SERVER_PASSWORD=change-me-before-deploy
TZ=Asia/Shanghai
+86
View File
@@ -0,0 +1,86 @@
additionalProperties:
formFields:
- default: 4096
edit: true
envKey: PANEL_APP_PORT_HTTP
labelEn: Web Port
labelZh: Web 端口
label:
en: Web Port
zh: Web 端口
zh-Hant: Web 連接埠
ja: Web ポート
ko: 웹 포트
ru: Веб-порт
ms: Port Web
pt-br: Porta Web
required: true
rule: paramPort
type: number
- default: ./data
edit: true
envKey: APP_DATA_DIR
labelEn: Data Directory
labelZh: 数据目录
label:
en: Data Directory
zh: 数据目录
zh-Hant: 資料目錄
ja: データディレクトリ
ko: 데이터 디렉터리
ru: Каталог данных
ms: Direktori Data
pt-br: Diretório de Dados
required: true
type: text
- default: opencode
edit: true
envKey: OPENCODE_SERVER_USERNAME
labelEn: Server Username
labelZh: 服务器用户名
label:
en: Server Username
zh: 服务器用户名
zh-Hant: 伺服器使用者名稱
ja: サーバーユーザー名
ko: 서버 사용자 이름
ru: Имя пользователя сервера
ms: Nama Pengguna Pelayan
pt-br: Nome de Usuario do Servidor
required: true
rule: paramCommon
type: text
- default: ''
edit: true
envKey: OPENCODE_SERVER_PASSWORD
labelEn: Server Password
labelZh: 服务器密码
label:
en: Server Password
zh: 服务器密码
zh-Hant: 伺服器密碼
ja: サーバーパスワード
ko: 서버 비밀번호
ru: Пароль сервера
ms: Kata Laluan Pelayan
pt-br: Senha do Servidor
random: true
required: true
rule: paramComplexity
type: password
- default: Asia/Shanghai
edit: true
envKey: TZ
labelEn: Timezone
labelZh: 时区
label:
en: Timezone
zh: 时区
zh-Hant: 時區
ja: タイムゾーン
ko: 시간대
ru: Часовой пояс
ms: Zon Waktu
pt-br: Fuso Horário
required: true
type: text
+35
View File
@@ -0,0 +1,35 @@
services:
opencode:
image: "ghcr.io/anomalyco/opencode:latest"
container_name: ${CONTAINER_NAME}
restart: unless-stopped
user: "1000:1000"
command: ["serve", "--hostname", "0.0.0.0", "--port", "4096"]
networks:
- 1panel-network
ports:
- "${PANEL_APP_PORT_HTTP}:4096"
volumes:
- "${APP_DATA_DIR}:/home/opencode"
environment:
- HOME=/home/opencode
- OPENCODE_SERVER_USERNAME=${OPENCODE_SERVER_USERNAME}
- OPENCODE_SERVER_PASSWORD=${OPENCODE_SERVER_PASSWORD}
- TZ=${TZ}
stop_grace_period: 15s
healthcheck:
test:
- CMD-SHELL
- >-
auth="$$(printf '%s:%s' "$${OPENCODE_SERVER_USERNAME}" "$${OPENCODE_SERVER_PASSWORD}" | base64 | tr -d '\n')";
wget -q -O /dev/null --header "Authorization: Basic $$auth" http://127.0.0.1:4096/global/health
interval: 1m
timeout: 5s
retries: 5
start_period: 20s
labels:
createdBy: "Apps"
networks:
1panel-network:
external: true
+37
View File
@@ -0,0 +1,37 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
ENV_FILE="${ENV_FILE:-$ROOT_DIR/.env}"
read_env_value() {
local value=""
[[ -f "$ENV_FILE" ]] || return 0
value="$(sed -n "s/^APP_DATA_DIR=//p" "$ENV_FILE" | tail -n 1)"
value="${value#\"}"
value="${value%\"}"
value="${value#\'}"
value="${value%\'}"
printf '%s\n' "$value"
}
data_dir_value="${APP_DATA_DIR:-$(read_env_value)}"
data_dir_value="${data_dir_value:-./data}"
data_dir_is_absolute=false
case "$data_dir_value" in
/) echo "refusing to use / as APP_DATA_DIR" >&2; exit 1 ;;
/*) data_dir="$data_dir_value"; data_dir_is_absolute=true ;;
*) data_dir="$ROOT_DIR/${data_dir_value#./}" ;;
esac
data_dir="$(readlink -f -- "$data_dir")"
case "$data_dir" in
/) echo "refusing to use / as APP_DATA_DIR" >&2; exit 1 ;;
esac
if [[ "$data_dir_is_absolute" == false && "$data_dir" != "$ROOT_DIR/"* ]]; then
echo "refusing relative APP_DATA_DIR outside the app directory" >&2
exit 1
fi
mkdir -p -- "$data_dir"
chown -R 1000:1000 -- "$data_dir"
@@ -0,0 +1,2 @@
#!/bin/bash
docker-compose down --volumes
+4
View File
@@ -0,0 +1,4 @@
#!/usr/bin/env bash
set -euo pipefail
exec "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/init.sh"
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB