-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathentrypoint.sh
More file actions
executable file
·209 lines (180 loc) · 7.73 KB
/
entrypoint.sh
File metadata and controls
executable file
·209 lines (180 loc) · 7.73 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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
#!/bin/bash
set -e
# Configuration
USER_NAME="${USER_NAME:-testdev}"
USER_HOME="/home/${USER_NAME}"
USER_PASSWORD="${TESTDEV_PASSWORD:-${USER_NAME}}"
echo "[entrypoint] Setting up user: ${USER_NAME}"
# Detect existing home ownership to align UID/GID (if it's not root)
# Default to 1000 if not found or if owned by root
FINAL_UID=1000
FINAL_GID=1000
if [ -d "${USER_HOME}" ]; then
EXISTING_UID=$(stat -c '%u' "${USER_HOME}")
EXISTING_GID=$(stat -c '%g' "${USER_HOME}")
echo "[entrypoint] Detected existing home volume ownership: ${EXISTING_UID}:${EXISTING_GID}"
# Only align if it's a non-root UID (>= 1000 is standard for users)
if [ "${EXISTING_UID}" -ge 1000 ]; then
FINAL_UID="${EXISTING_UID}"
FINAL_GID="${EXISTING_GID}"
echo "[entrypoint] Aligning container user with UID ${FINAL_UID}"
else
echo "[entrypoint] Volume is owned by system/root. Using default UID 1000."
fi
fi
# Check for conflicting user with FINAL_UID
CONFLICT_USER=$(getent passwd "${FINAL_UID}" | cut -d: -f1)
if [ -n "${CONFLICT_USER}" ] && [ "${CONFLICT_USER}" != "${USER_NAME}" ]; then
echo "[entrypoint] Removing conflicting user '${CONFLICT_USER}' with UID ${FINAL_UID}"
userdel -r "${CONFLICT_USER}" || true
fi
# Check for conflicting group with FINAL_GID
CONFLICT_GROUP=$(getent group "${FINAL_GID}" | cut -d: -f1)
if [ -n "${CONFLICT_GROUP}" ] && [ "${CONFLICT_GROUP}" != "${USER_NAME}" ]; then
echo "[entrypoint] Renaming conflicting group '${CONFLICT_GROUP}' to '${USER_NAME}'"
groupmod -n "${USER_NAME}" "${CONFLICT_GROUP}" || true
fi
# Create group if it doesn't exist
if ! getent group "${FINAL_GID}" >/dev/null; then
groupadd -g "${FINAL_GID}" "${USER_NAME}" || true
fi
# Create or Update user to match detected UID/GID
if ! id -u "${USER_NAME}" >/dev/null 2>&1; then
# Create new user
useradd -m -s /bin/bash -u "${FINAL_UID}" -g "${FINAL_GID}" "${USER_NAME}"
echo "${USER_NAME}:${USER_PASSWORD}" | chpasswd
usermod -aG sudo "${USER_NAME}"
else
# Update existing user to match desired UID/GID
echo "[entrypoint] Updating existing user '${USER_NAME}' to UID ${FINAL_UID}"
usermod -u "${FINAL_UID}" "${USER_NAME}" || true
groupmod -g "${FINAL_GID}" "${USER_NAME}" || true
fi
# Bootstrap skeleton files if missing
if [ ! -f "${USER_HOME}/.bashrc" ]; then
echo "[entrypoint] Standard skeleton files missing. Bootstrapping from /etc/skel..."
# Use -n to avoid overwriting anything if some files DO exist
cp -rn /etc/skel/. "${USER_HOME}/"
chown -R "${USER_NAME}:${USER_NAME}" "${USER_HOME}/."
fi
# Ensure home directory permissions are truly correct at the root level
chown "${USER_NAME}:${USER_NAME}" "${USER_HOME}"
# Start DBUS
echo "[entrypoint] Starting dbus"
mkdir -p /run/dbus
rm -f /run/dbus/pid /run/dbus/dbus.pid
dbus-daemon --system --fork --nopidfile || true
# Cleanup and Setup X11 directory
echo "[entrypoint] Surgical cleanup of X11 and VNC state"
rm -rf /tmp/.X11-unix /tmp/.X*-lock /tmp/.X11-pipe
mkdir -p /tmp/.X11-unix
chmod 1777 /tmp/.X11-unix
# KasmVNC Setup
KASM_CONFIG_DIR="${USER_HOME}/.vnc"
# KasmVNC 1.x (1.3.3) hardcodes its internal password file check to ~/.kasmpasswd
PASSWD_FILE="${USER_HOME}/.kasmpasswd"
CERT_DIR="${KASM_CONFIG_DIR}/ssl"
# Wipe .vnc directory for fresh v2 migration if needed
if [ ! -f "${KASM_CONFIG_DIR}/kasmvnc.yaml" ]; then
echo "[entrypoint] Fresh KasmVNC setup: Cleaning .vnc directory"
fi
mkdir -p "${KASM_CONFIG_DIR}" "${CERT_DIR}"
# Generate self-signed SSL certificate (internal only, requirement disabled)
if [ ! -f "${CERT_DIR}/cert.pem" ]; then
echo "[entrypoint] Generating self-signed SSL certificate"
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout "${CERT_DIR}/key.pem" \
-out "${CERT_DIR}/cert.pem" \
-subj "/C=US/ST=State/L=City/O=Organization/CN=localhost"
fi
# Create xstartup script for XFCE
cat <<EOF > "${KASM_CONFIG_DIR}/xstartup"
#!/bin/sh
export DISPLAY=:1
unset SESSION_MANAGER
unset DBUS_SESSION_BUS_ADDRESS
cd "${USER_HOME}"
/usr/bin/startxfce4
EOF
chmod +x "${KASM_CONFIG_DIR}/xstartup"
# Fix ownership of everything we just created
chown -R "${USER_NAME}:${USER_NAME}" "${KASM_CONFIG_DIR}"
# Create a ModernAuth password file to bypass KasmVNC's interactive prompt.
# Even though we use -DisableBasicAuth, KasmVNC validates the password file exists
# and contains at least one user with write permissions (required for session control).
if [ ! -f "${PASSWD_FILE}" ]; then
echo "[entrypoint] Direct seeding VNC password file (auth handled by Traefik)"
# Format is: username:SHA256_hash:permissions
# The hash below corresponds to 'dummypass'
echo "${USER_NAME}:\$5\$kasm\$3SXAeRDy21bx0XeiL8FPQg6VP3nP2JQR3ofIyuIPuo2:w" > "${PASSWD_FILE}"
chmod 600 "${PASSWD_FILE}"
chown "${USER_NAME}:${USER_NAME}" "${PASSWD_FILE}"
else
echo "[entrypoint] Found existing VNC password file, preserving credentials."
# Ensure permissions are correct
chmod 600 "${PASSWD_FILE}"
chown "${USER_NAME}:${USER_NAME}" "${PASSWD_FILE}"
fi
# Create a robust kasmvnc.yaml for KasmVNC 1.3.3
# Note: We use -DisableBasicAuth and -SecurityTypes None, so no password file needed
# Traefik handles all authentication via BasicAuth middleware
cat <<EOF > "${KASM_CONFIG_DIR}/kasmvnc.yaml"
# Managed by entrypoint.sh
network:
interface: 0.0.0.0
websocket_port: 6901
ssl:
require_ssl: true
pem_certificate: ${CERT_DIR}/cert.pem
pem_key: ${CERT_DIR}/key.pem
security:
brute_force_protection:
blacklist_threshold: 0
server:
advanced:
kasm_password_file: ${PASSWD_FILE}
http:
httpd_directory: /usr/share/kasmvnc/www
command_line:
prompt: false
EOF
chown "${USER_NAME}:${USER_NAME}" "${KASM_CONFIG_DIR}/kasmvnc.yaml"
# Ensure the password file is ALSO owned by the user and in the right place
chown "${USER_NAME}:${USER_NAME}" "${PASSWD_FILE}"
# PATCH KasmVNC to force disable UDP and bypass STUN/ICE
# Injecting -udpPort 0 and -publicIP 127.0.0.1 into LegacyModeArgsToCmd
echo "[entrypoint] Patching kasmvncserver to force disable UDP/STUN via publicIP"
sed -i 's/.*-rfbwait.*=>.*30000.*/ -rfbwait => 30000, "-udpPort" => 0, "-publicIP" => "127.0.0.1"/' /usr/bin/kasmvncserver
# Surgical patch of KasmVNC to bypass the interactive user check.
# Since we use Traefik for auth, this check is redundant and blocking in Docker.
echo "[entrypoint] Patching kasmvncserver to bypass interactive user validation"
sed -i 's/sub AtLeastOneUserWithWriteAccessConfigured {/sub AtLeastOneUserWithWriteAccessConfigured { return 1;/' /usr/bin/kasmvncserver
# Ensure ownership of home directory
echo "[entrypoint] Enforcing ownership of ${USER_HOME}"
chown -R "${USER_NAME}:${USER_NAME}" "${USER_HOME}"
# Change to user home directory
echo "[entrypoint] Setting working directory to ${USER_HOME}"
cd "${USER_HOME}"
# Start remote-dev-box-proxy (Tier 2 Proxy)
# Ensure socket is clean and accessible
rm -f /tmp/rdb-proxy.sock
echo "[entrypoint] Starting remote-dev-box-proxy (daemon) as user ${USER_NAME} on port 8080"
# Use sudo -u to run as user with clean context
sudo -u "${USER_NAME}" bash -c "rm -f /tmp/rdb-proxy.sock && rdb serve &"
echo "[entrypoint] Starting kasmvncserver (foreground)"
# DEBUG: Check config and permissions
echo "[entrypoint] DEBUG: Listing .vnc directory:"
ls -laR "${KASM_CONFIG_DIR}"
echo "[entrypoint] DEBUG: Content of kasmvnc.yaml:"
cat "${KASM_CONFIG_DIR}/kasmvnc.yaml"
echo "[entrypoint] DEBUG: Content of passwd file:"
cat "${PASSWD_FILE}"
# Run as the user
# Adding -DisableBasicAuth and -SecurityTypes None to allow Traefik to handle auth entirely.
exec sudo -u "${USER_NAME}" kasmvncserver :1 \
-config "${KASM_CONFIG_DIR}/kasmvnc.yaml" \
-interface 0.0.0.0 \
-xstartup "${KASM_CONFIG_DIR}/xstartup" \
-DisableBasicAuth \
-SecurityTypes None \
-fg