Skip to content

Commit ad9ab25

Browse files
author
sertdev
committed
feat(runtime): replace t3 editor with code-server
1 parent 5cfc59a commit ad9ab25

5 files changed

Lines changed: 261 additions & 53 deletions

File tree

runtime/.bashrc

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,3 @@ PROMPT_COMMAND=_ps1_update
5151
# cd "$HOME/next"
5252
# fi
5353

54-
# Auto-start Claude Code CLI on first terminal connection only
55-
# Use a file flag that persists across ttyd reconnections
56-
CLAUDE_FLAG_FILE="/tmp/.claude_started"
57-
58-
if [ ! -f "$CLAUDE_FLAG_FILE" ]; then
59-
touch "$CLAUDE_FLAG_FILE"
60-
echo "🤖 Starting Claude Code CLI..."
61-
claude
62-
fi

runtime/.tmux.conf

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# FullstackAgent tmux configuration
2+
# Persistent terminal sessions for web terminal
3+
4+
# Disable status bar for clean terminal appearance
5+
set -g status off
6+
7+
# 256 color and true color support
8+
set -g default-terminal "xterm-256color"
9+
set -ga terminal-overrides ",xterm-256color:Tc"
10+
11+
# Large scrollback buffer
12+
set -g history-limit 50000
13+
14+
# Enable mouse support (scroll, click, resize panes)
15+
set -g mouse on

runtime/Dockerfile

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,18 +20,14 @@ LABEL maintainer="FullstackAgent" \
2020
ENV DEBIAN_FRONTEND=noninteractive \
2121
NODE_VERSION=22.x \
2222
NEXT_VERSION=15.5.9 \
23-
CLAUDE_CODE_VERSION=latest \
23+
CODE_SERVER_VERSION=4.104.3 \
2424
PATH="/root/.local/bin:/home/fulling/.local/bin:$PATH" \
2525
TERM=xterm-256color \
2626
COLORTERM=truecolor \
2727
LANG=en_US.UTF-8 \
2828
LC_ALL=en_US.UTF-8 \
29-
ANTHROPIC_BASE_URL="" \
30-
ANTHROPIC_AUTH_TOKEN="" \
31-
ANTHROPIC_MODEL="" \
32-
ANTHROPIC_SMALL_FAST_MODEL="" \
33-
GEMINI_API_KEY="" \
34-
OPENAI_API_KEY="" \
29+
CODEX_API_KEY="" \
30+
CODEX_BASE_URL="" \
3531
DOCKER_HUB_NAME="" \
3632
DOCKER_HUB_PASSWD=""
3733

@@ -81,12 +77,10 @@ RUN set -eux; \
8177

8278
# -----------------------------------------------------------------------------
8379
# Install global npm packages in a single layer
84-
# Includes CLI tools for Next.js, package managers, deployment, and AI assistance
80+
# Includes CLI tools for Next.js, package managers, deployment, and Codex AI assistant
8581
# -----------------------------------------------------------------------------
8682
RUN npm install -g \
87-
@anthropic-ai/claude-code \
88-
@google/gemini-cli \
89-
@openai/codex \
83+
@openai/codex@latest \
9084
create-next-app@${NEXT_VERSION} \
9185
pnpm \
9286
prisma \
@@ -163,7 +157,9 @@ RUN set -eux; \
163157
apt-get update; \
164158
apt-get install -y --no-install-recommends \
165159
bat \
160+
bubblewrap \
166161
dnsutils \
162+
dtach \
167163
fd-find \
168164
gh \
169165
htop \
@@ -206,11 +202,20 @@ WORKDIR /home/fulling/next
206202
# Copy configuration files (placed before user switch for better caching)
207203
# entrypoint.sh: Container startup script
208204
# ttyd-startup.sh: Startup script for ttyd (session tracking, welcome message)
209-
# .bashrc: Shell configuration with custom prompt and Claude CLI auto-start
205+
# .bashrc: Shell configuration with custom prompt
210206
# -----------------------------------------------------------------------------
211-
COPY --chmod=755 entrypoint.sh /usr/local/bin/entrypoint.sh
212-
COPY --chmod=755 ttyd-startup.sh /usr/local/bin/ttyd-startup.sh
213-
COPY --chmod=644 .bashrc /etc/skel/.bashrc
207+
COPY entrypoint.sh /usr/local/bin/entrypoint.sh
208+
COPY ttyd-auth.sh /usr/local/bin/ttyd-auth.sh
209+
COPY .bashrc /etc/skel/.bashrc
210+
COPY .tmux.conf /etc/skel/.tmux.conf
211+
RUN chmod 755 /usr/local/bin/entrypoint.sh /usr/local/bin/ttyd-auth.sh && chmod 644 /etc/skel/.bashrc /etc/skel/.tmux.conf
212+
213+
# -----------------------------------------------------------------------------
214+
# Install code-server for the embedded editor
215+
# -----------------------------------------------------------------------------
216+
RUN set -eux; \
217+
curl -fsSL https://code-server.dev/install.sh | sh -s -- --version "${CODE_SERVER_VERSION}"; \
218+
code-server --version
214219

215220
# =============================================================================
216221
# Stage 2: Next.js project template preparation
@@ -301,7 +306,7 @@ RUN set -eux; \
301306
# 5432: PostgreSQL client connections
302307
# 7681: ttyd web terminal
303308
# -----------------------------------------------------------------------------
304-
EXPOSE 3000 3001 5000 5173 8080 8000 5432 7681
309+
EXPOSE 3000 3001 3773 5000 5173 8080 8000 5432 7681
305310

306311
# -----------------------------------------------------------------------------
307312
# Health check configuration
@@ -316,6 +321,6 @@ HEALTHCHECK --interval=2m --timeout=30s --start-period=1m --retries=3 \
316321
# -----------------------------------------------------------------------------
317322
# Container entrypoint
318323
# Starts ttyd web terminal which provides browser-based shell access
319-
# The .bashrc will auto-start Claude Code CLI on first connection
324+
# Codex configuration is written from environment variables at startup
320325
# -----------------------------------------------------------------------------
321326
CMD ["/usr/local/bin/entrypoint.sh"]

runtime/entrypoint.sh

Lines changed: 124 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,110 @@
11
#!/bin/bash
22
# =============================================================================
3-
# ttyd Entrypoint Script
3+
# Sandbox Entrypoint Script
44
# =============================================================================
55
#
6-
# Starts ttyd web terminal with HTTP Basic Auth enabled.
6+
# Sets up Codex configuration, starts code-server, and starts ttyd web terminal.
77
#
88
# Authentication Flow:
9-
# 1. ttyd validates credentials at HTTP/WebSocket layer via -c parameter
10-
# 2. URL format: ?authorization=base64(user:password)&arg=SESSION_ID
11-
# 3. ttyd-startup.sh handles session tracking (not auth) for file upload cwd detection
9+
# ttyd-auth.sh receives the access token via ?arg=TOKEN and validates it
10+
# against the TTYD_ACCESS_TOKEN environment variable.
1211
#
1312
# Required Environment Variables:
14-
# TTYD_ACCESS_TOKEN - Password for HTTP Basic Auth (username is 'user')
13+
# TTYD_ACCESS_TOKEN - Access token for terminal authentication
1514
#
16-
# Optional URL Parameters (via -a flag):
17-
# arg=SESSION_ID - Terminal session ID for file upload directory tracking
15+
# Optional Environment Variables:
16+
# CODEX_API_KEY - API key for Codex (written to ~/.codex/auth.json)
17+
# CODEX_BASE_URL - LLM API base URL for Codex (written to ~/.codex/config.toml)
1818
#
1919
# =============================================================================
2020

2121
set -euo pipefail
2222

23+
FULLING_USER="${FULLING_USER:-fulling}"
24+
FULLING_GROUP="${FULLING_GROUP:-fulling}"
25+
FULLING_HOME="${FULLING_HOME:-/home/fulling}"
26+
SKEL_DIR="${SKEL_DIR:-/etc/skel}"
27+
TTYD_AUTH_SCRIPT="${TTYD_AUTH_SCRIPT:-/usr/local/bin/ttyd-auth.sh}"
28+
FULLING_WORKSPACE="${FULLING_WORKSPACE:-$FULLING_HOME/next}"
29+
EDITOR_PASSWORD="${EDITOR_PASSWORD:-${TTYD_ACCESS_TOKEN:-}}"
30+
31+
maybe_chown() {
32+
if [ "$(id -u)" -eq 0 ]; then
33+
chown "$@"
34+
fi
35+
}
36+
37+
mkdir -p "$FULLING_HOME"
38+
mkdir -p "$FULLING_WORKSPACE"
39+
export HOME="$FULLING_HOME"
40+
export USER="$FULLING_USER"
41+
export LOGNAME="$FULLING_USER"
42+
export CODEX_HOME="${CODEX_HOME:-$FULLING_HOME/.codex}"
43+
2344
# -----------------------------------------------------------------------------
2445
# Validate required environment variables
2546
# -----------------------------------------------------------------------------
26-
if [ -z "$TTYD_ACCESS_TOKEN" ]; then
47+
if [ -z "${TTYD_ACCESS_TOKEN:-}" ]; then
2748
echo "ERROR: TTYD_ACCESS_TOKEN environment variable is not set"
2849
echo "This is required for terminal authentication"
2950
exit 1
3051
fi
3152

3253
# -----------------------------------------------------------------------------
33-
# Build HTTP Basic Auth credential
34-
# Format: username:password (username is fixed as 'user')
54+
# Copy shell config files from skeleton to PVC-mounted home directory
55+
# On first run the PVC is empty, so .bashrc needs to be copied
3556
# -----------------------------------------------------------------------------
36-
TTYD_CREDENTIAL="user:${TTYD_ACCESS_TOKEN}"
57+
for skelfile in .bashrc .tmux.conf; do
58+
if [ ! -f "$FULLING_HOME/$skelfile" ] && [ -f "$SKEL_DIR/$skelfile" ]; then
59+
cp "$SKEL_DIR/$skelfile" "$FULLING_HOME/$skelfile"
60+
maybe_chown "$FULLING_USER:$FULLING_GROUP" "$FULLING_HOME/$skelfile"
61+
fi
62+
done
63+
64+
# -----------------------------------------------------------------------------
65+
# Setup Codex configuration
66+
# Writes ~/.codex/config.toml and ~/.codex/auth.json from environment variables.
67+
# These are regenerated on every container start so settings changes take effect
68+
# after pod restart.
69+
# -----------------------------------------------------------------------------
70+
CODEX_CONFIG_DIR="$CODEX_HOME"
71+
CODEX_CONFIG_FILE="${CODEX_CONFIG_DIR}/config.toml"
72+
CODEX_AUTH_FILE="${CODEX_CONFIG_DIR}/auth.json"
73+
74+
# Write config.toml if CODEX_BASE_URL is set
75+
if [ -n "${CODEX_BASE_URL:-}" ]; then
76+
mkdir -p "$CODEX_CONFIG_DIR"
77+
cat > "$CODEX_CONFIG_FILE" << CODEX_CONFIG_EOF
78+
service_tier = "fast"
79+
model_provider = "litellm"
80+
81+
[model_providers.litellm]
82+
name = "OpenAI"
83+
base_url = "${CODEX_BASE_URL}"
84+
wire_api = "responses"
85+
requires_openai_auth = true
86+
CODEX_CONFIG_EOF
87+
maybe_chown "$FULLING_USER:$FULLING_GROUP" "$CODEX_CONFIG_FILE"
88+
echo "✓ Codex config initialized (base_url: ${CODEX_BASE_URL})"
89+
fi
90+
91+
# Write auth.json if CODEX_API_KEY is set
92+
if [ -n "${CODEX_API_KEY:-}" ]; then
93+
mkdir -p "$CODEX_CONFIG_DIR"
94+
cat > "$CODEX_AUTH_FILE" << CODEX_AUTH_EOF
95+
{
96+
"auth_mode": "apikey",
97+
"OPENAI_API_KEY": "${CODEX_API_KEY}"
98+
}
99+
CODEX_AUTH_EOF
100+
maybe_chown "$FULLING_USER:$FULLING_GROUP" "$CODEX_AUTH_FILE"
101+
echo "✓ Codex auth configured"
102+
fi
103+
104+
# Ensure proper ownership of codex config directory
105+
if [ -d "$CODEX_CONFIG_DIR" ]; then
106+
maybe_chown -R "$FULLING_USER:$FULLING_GROUP" "$CODEX_CONFIG_DIR" 2>/dev/null || true
107+
fi
37108

38109
# -----------------------------------------------------------------------------
39110
# Terminal theme configuration
@@ -62,34 +133,60 @@ THEME='theme={
62133
}'
63134

64135
# -----------------------------------------------------------------------------
65-
# Verify startup script exists
136+
# Configure and start code-server as a background daemon.
137+
# The editor listens on port 3773 and serves the project workspace.
138+
# -----------------------------------------------------------------------------
139+
CODE_SERVER_CONFIG_DIR="${FULLING_HOME}/.config/code-server"
140+
CODE_SERVER_CONFIG_FILE="${CODE_SERVER_CONFIG_DIR}/config.yaml"
141+
142+
mkdir -p "$CODE_SERVER_CONFIG_DIR"
143+
cat > "$CODE_SERVER_CONFIG_FILE" << CODE_SERVER_CONFIG_EOF
144+
bind-addr: 0.0.0.0:3773
145+
auth: password
146+
password: ${EDITOR_PASSWORD}
147+
cert: false
148+
CODE_SERVER_CONFIG_EOF
149+
maybe_chown -R "$FULLING_USER:$FULLING_GROUP" "$CODE_SERVER_CONFIG_DIR"
150+
151+
if command -v code-server >/dev/null 2>&1; then
152+
echo "Starting code-server (port 3773)..."
153+
PASSWORD="$EDITOR_PASSWORD" \
154+
HOME="$HOME" \
155+
USER="$USER" \
156+
LOGNAME="$LOGNAME" \
157+
CODEX_HOME="$CODEX_HOME" \
158+
nohup code-server "$FULLING_WORKSPACE" > /tmp/code-server.log 2>&1 &
159+
echo "✓ code-server started (PID: $!)"
160+
else
161+
echo "ERROR: code-server is not installed"
162+
exit 1
163+
fi
164+
165+
# -----------------------------------------------------------------------------
166+
# Verify auth script exists
66167
# -----------------------------------------------------------------------------
67-
if [ ! -f /usr/local/bin/ttyd-startup.sh ]; then
68-
echo "ERROR: ttyd-startup.sh not found at /usr/local/bin/ttyd-startup.sh"
168+
if [ ! -f "$TTYD_AUTH_SCRIPT" ]; then
169+
echo "ERROR: ttyd-auth.sh not found at $TTYD_AUTH_SCRIPT"
69170
exit 1
70171
fi
71172

72173
# -----------------------------------------------------------------------------
73-
# Start ttyd with authentication
174+
# Start ttyd with token-based authentication
74175
# -----------------------------------------------------------------------------
75176
# Parameters:
76-
# -T xterm-256color : Terminal type (widely supported)
177+
# -T xterm-256color : Terminal type
77178
# -W : Enable WebSocket compression
78-
# -a : Allow URL arguments (?arg=SESSION_ID) to be passed to command
79-
# -c credential : HTTP Basic Auth (user:password)
179+
# -a : Allow URL arguments (?arg=TOKEN&arg=SESSION_ID)
80180
# -t theme : Terminal color theme
81181
#
82-
# The command (ttyd-startup.sh) receives URL arguments:
83-
# $1 = SESSION_ID (from ?arg=...)
84-
#
85-
# Authentication happens at HTTP/WebSocket level by ttyd.
86-
# ttyd-startup.sh only handles session tracking for file upload cwd detection.
182+
# ttyd-auth.sh receives:
183+
# $1 = ACCESS_TOKEN (from first ?arg=)
184+
# $2 = SESSION_ID (from second ?arg=)
87185
# -----------------------------------------------------------------------------
88-
echo "Starting ttyd with HTTP Basic Auth..."
186+
echo "Starting ttyd..."
89187
exec ttyd \
90188
-T xterm-256color \
91189
-W \
92190
-a \
93-
-c "$TTYD_CREDENTIAL" \
94191
-t "$THEME" \
95-
/usr/local/bin/ttyd-startup.sh
192+
"$TTYD_AUTH_SCRIPT"

0 commit comments

Comments
 (0)