This repository was archived by the owner on May 4, 2026. It is now read-only.
forked from open-webui/open-terminal
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathentrypoint.sh
More file actions
executable file
·151 lines (130 loc) · 6.04 KB
/
entrypoint.sh
File metadata and controls
executable file
·151 lines (130 loc) · 6.04 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
#!/bin/bash
set -e
# -----------------------------------------------------------------------
# Docker-secrets support: resolve <VAR>_FILE → <VAR>
# Follows the convention used by the official PostgreSQL image.
# -----------------------------------------------------------------------
file_env() {
local var="$1"
local fileVar="${var}_FILE"
local def="${2:-}"
if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then
printf >&2 'error: both %s and %s are set (but are exclusive)\n' "$var" "$fileVar"
exit 1
fi
local val="$def"
if [ "${!var:-}" ]; then
val="${!var}"
elif [ "${!fileVar:-}" ]; then
val="$(< "${!fileVar}")"
fi
export "$var"="$val"
unset "$fileVar"
}
file_env 'OPEN_TERMINAL_API_KEY'
# Fix permissions of the home directory if the user doesn't own it
# Find out who owns /home/user
OWNER=$(stat -c '%U' /home/user 2>/dev/null || echo "user")
if [ "$OWNER" != "user" ]; then
# We use sudo because the container runs as 'user' but has passwordless sudo
sudo chown -R user:user /home/user 2>/dev/null || true
fi
# Seed essential dotfiles when /home/user is bind-mounted empty
# (Docker does not populate bind-mounts with image contents)
if [ ! -f "$HOME/.bashrc" ]; then
cp /etc/skel/.bashrc "$HOME/.bashrc" 2>/dev/null || true
fi
if [ ! -f "$HOME/.profile" ]; then
cp /etc/skel/.profile "$HOME/.profile" 2>/dev/null || true
fi
mkdir -p "$HOME/.local/bin"
# Docker socket access — add user to the socket's group if mounted
if [ -S /var/run/docker.sock ]; then
SOCK_GID=$(stat -c '%g' /var/run/docker.sock)
if ! getent group "$SOCK_GID" > /dev/null 2>&1; then
sudo groupadd -g "$SOCK_GID" docker-host
fi
SOCK_GROUP=$(getent group "$SOCK_GID" | cut -d: -f1)
sudo usermod -aG "$SOCK_GROUP" user
fi
# Auto-install system packages
if [ -n "${OPEN_TERMINAL_PACKAGES:-}" ]; then
echo "Installing system packages: $OPEN_TERMINAL_PACKAGES"
sudo apt-get update -qq && sudo apt-get install -y --no-install-recommends $OPEN_TERMINAL_PACKAGES
sudo rm -rf /var/lib/apt/lists/*
fi
# Auto-install Python packages
if [ -n "${OPEN_TERMINAL_PIP_PACKAGES:-}" ]; then
echo "Installing pip packages: $OPEN_TERMINAL_PIP_PACKAGES"
pip install --no-cache-dir $OPEN_TERMINAL_PIP_PACKAGES
fi
# -----------------------------------------------------------------------
# Network egress filtering via DNS whitelist + iptables + capability drop
#
# OPEN_TERMINAL_ALLOWED_DOMAINS unset → full access
# OPEN_TERMINAL_ALLOWED_DOMAINS="" → block ALL outbound
# OPEN_TERMINAL_ALLOWED_DOMAINS="a,b" → DNS whitelist (dnsmasq)
#
# Restricted mode runs a local dnsmasq that only resolves whitelisted
# domains. iptables blocks external DNS so the container must use the
# local resolver. CAP_NET_ADMIN is permanently dropped via capsh.
# -----------------------------------------------------------------------
if [ "${OPEN_TERMINAL_ALLOWED_DOMAINS+set}" = "set" ]; then
if ! command -v iptables &>/dev/null; then
echo "WARNING: iptables not found — skipping egress firewall"
exec open-terminal "$@"
fi
# Flush any prior OUTPUT rules
sudo iptables -F OUTPUT 2>/dev/null || true
# Always allow loopback + established connections
sudo iptables -A OUTPUT -o lo -j ACCEPT
sudo iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
if [ -z "$OPEN_TERMINAL_ALLOWED_DOMAINS" ]; then
# ── Deny-all mode ──────────────────────────────────────────────
echo "Egress: blocking ALL outbound traffic"
sudo iptables -A OUTPUT -j DROP
else
# ── Restricted mode (DNS whitelist + ipset) ────────────────────
echo "Egress: DNS whitelist — $OPEN_TERMINAL_ALLOWED_DOMAINS"
# Capture the current upstream nameserver before we override resolv.conf
UPSTREAM_DNS=$(grep -m1 '^nameserver' /etc/resolv.conf | awk '{print $2}')
UPSTREAM_DNS="${UPSTREAM_DNS:-8.8.8.8}"
# Create ipset for dynamically resolved IPs
sudo ipset create allowed hash:ip -exist
# Generate dnsmasq config:
# - NXDOMAIN for everything by default
# - Forward allowed domains to upstream DNS
# - Auto-add resolved IPs to the 'allowed' ipset
sudo mkdir -p /etc/dnsmasq.d
{
echo "no-resolv"
echo "no-hosts"
echo "listen-address=127.0.0.1"
echo "port=53"
echo "address=/#/" # NXDOMAIN for everything by default
IFS=',' read -ra DOMAINS <<< "$OPEN_TERMINAL_ALLOWED_DOMAINS"
for domain in "${DOMAINS[@]}"; do
domain=$(echo "$domain" | xargs) # trim
[ -z "$domain" ] && continue
# Strip wildcard prefix — dnsmasq matches all subdomains natively
domain="${domain#\*.}"
echo "server=/${domain}/${UPSTREAM_DNS}"
echo "ipset=/${domain}/allowed"
echo " ✓ ${domain} (+ subdomains)" >&2
done
} | sudo tee /etc/dnsmasq.d/egress.conf > /dev/null
# Start dnsmasq as a background daemon
sudo dnsmasq --conf-file=/etc/dnsmasq.d/egress.conf
echo "dnsmasq started (upstream: ${UPSTREAM_DNS})"
# Point the container at our local resolver
echo "nameserver 127.0.0.1" | sudo tee /etc/resolv.conf > /dev/null
# iptables: allow ONLY resolved IPs (via ipset) + block everything else
sudo iptables -A OUTPUT -p udp --dport 53 -j DROP # block external DNS
sudo iptables -A OUTPUT -p tcp --dport 53 -j DROP # block external DNS
sudo iptables -A OUTPUT -m set --match-set allowed dst -j ACCEPT # allow resolved IPs
sudo iptables -A OUTPUT -j DROP # drop everything else
fi
echo "Egress firewall active — dropping CAP_NET_ADMIN permanently"
exec capsh --drop=cap_net_admin -- -c "exec open-terminal $*"
fi
exec open-terminal "$@"