Repository navigation
Docker
Image: jinqians/snell-server
Tags
| Tag | Version | Notes |
|---|---|---|
latest |
Snell v5.0.1 | Pinned to the v5 channel, never auto-jumps to v6 |
v4 |
Snell v4.1.1 | Latest in the v4 channel |
v5 |
Snell v5.0.1 | Latest in the v5 channel |
v6 |
Snell v6.0.0rc2 | Latest in the v6 channel (pre-release) |
v4.0.0 v4.0.1 v4.1.0 v4.1.1
|
Snell v4 | Pinned versions |
v5.0.0 v5.0.1
|
Snell v5 | Pinned versions |
v6.0.0b1 … v6.0.0b4 v6.0.0rc v6.0.0rc2
|
Snell v6 | Pinned pre-releases |
Architectures: v4 / v5 ship amd64, arm64, armv7; v6 has no upstream armv7 build, so
amd64 and arm64 only.
Alpine hosts: first put the docker service in the
defaultrunlevel as described in Enabling Docker on Alpine, otherwise dockerd won't start after a reboot and every container goes offline.
The container runs as the unprivileged user
nobody(uid 65534), so a mounted config directory must be writable by it, or the entrypoint can't generate the config. Run once before starting:mkdir -p ./snell-config && chown -R 65534:65533 ./snell-config
docker run -d --name snell-server \
--restart unless-stopped \
-p 6160:6160/tcp \
-p 6160:6160/udp \
-e SNELL_VER=v5 \
-e SNELL_PORT=6160 \
-v ./snell-config:/etc/snell \
jinqians/snell-server:v5
# print the client config
docker logs snell-serverThe Snell backend stays on 127.0.0.1 inside the container, so there is no need to
publish 6160.
docker run -d --name snell-shadowtls \
--restart unless-stopped \
-p 8443:8443/tcp \
-e SNELL_VER=v5 \
-e SNELL_PORT=6160 \
-e SNELL_LISTEN_HOST=127.0.0.1 \
-e SHADOWTLS_ENABLE=1 \
-e SHADOWTLS_PORT=8443 \
-e SHADOWTLS_SNI=www.microsoft.com \
-v ./snell-config:/etc/snell \
jinqians/snell-server:v5
docker logs snell-shadowtlsv6 needs SNELL_MODE; see Snell v6-only options for what the
values mean. Use the :v6 tag and SNELL_VER=v6 — both are required.
docker run -d --name snell-v6 --restart unless-stopped \
-p 6160:6160/tcp -p 6160:6160/udp \
-e SNELL_VER=v6 \
-e SNELL_PORT=6160 \
-e SNELL_MODE=default \
-e SNELL_DNS_IP_PREFERENCE=default \
-v ./snell-config:/etc/snell \
jinqians/snell-server:v6
docker logs snell-v6Docker Compose:
services:
snell:
image: jinqians/snell-server:v6
container_name: snell-v6
restart: unless-stopped
ports:
- "6160:6160/tcp"
- "6160:6160/udp"
environment:
- SNELL_VER=v6
- SNELL_PORT=6160
- SNELL_MODE=default # default / unshaped / unsafe-raw
- SNELL_DNS_IP_PREFERENCE=default # default / prefer-ipv4 / prefer-ipv6 / ipv4-only / ipv6-only
# - SNELL_DNS=1.1.1.1,8.8.8.8
volumes:
- ./snell-config:/etc/snellCommon combinations (full table in Recommended combinations):
-e SNELL_MODE=default -e SNELL_DNS_IP_PREFERENCE=default # general use
-e SNELL_MODE=unshaped -e SNELL_DNS_IP_PREFERENCE=default # clean link, ~10% more throughput
-e SNELL_MODE=default -e SNELL_DNS_IP_PREFERENCE=ipv4-only # VPS without IPv6 egress
-e SNELL_MODE=default -e SNELL_DNS_IP_PREFERENCE=ipv6-only # IPv6-only VPSThe log prints the client config with mode filled in — the client's mode must match:
Snell = snell, 1.2.3.4, 6160, psk = xxx, version = 6, mode = unshaped, reuse = true, tfo = true
⚠️ Changing v6 options later: environment variables only apply when the config file is first generated. Oncesnell-server.confexists in the mounted directory, changingSNELL_MODEand restarting does nothing — the container says so in its log. Two ways to actually change it:# Option 1: edit the config file (keeps the PSK, recommended) sed -i 's/^mode = .*/mode = unshaped/' ./snell-config/snell-server.conf docker restart snell-v6 # Option 2: delete it and let the container regenerate (PSK changes — update clients) rm ./snell-config/snell-server.conf docker restart snell-v6
Change both the image tag and SNELL_VER. Deleting the old config regenerates the
PSK; keeping it reuses the existing one:
docker rm -f snell-server
rm -f ./snell-config/snell-server.conf # skip this to keep the current PSK
docker run -d --name snell-server \
--restart unless-stopped \
-p 6160:6160/tcp -p 6160:6160/udp \
-e SNELL_VER=v6 -e SNELL_PORT=6160 -e SNELL_MODE=default \
-v ./snell-config:/etc/snell \
jinqians/snell-server:v6./docker/build-docker-images.sh # all channels and versions
USE_BUILDX=1 PUSH=1 ./docker/build-docker-images.sh # multi-arch build and pushSnell only — create compose.yml:
services:
snell:
image: jinqians/snell-server:v5
container_name: snell-server
restart: unless-stopped
ports:
- "6160:6160/tcp"
- "6160:6160/udp"
environment:
- SNELL_VER=v5
- SNELL_PORT=6160
# - SNELL_PSK=your_psk # random on first start if unset
# - SNELL_SERVER_IP=1.2.3.4 # auto-probed if unset
# - SNELL_NODE_NAME=HK # node name in the printed config
volumes:
- ./snell-config:/etc/snellSnell + ShadowTLS:
services:
snell-shadowtls:
image: jinqians/snell-server:v5
container_name: snell-shadowtls
restart: unless-stopped
ports:
- "8443:8443/tcp"
environment:
- SNELL_VER=v5
- SNELL_PORT=6160
- SNELL_LISTEN_HOST=127.0.0.1
- SHADOWTLS_ENABLE=1
- SHADOWTLS_PORT=8443
- SHADOWTLS_SNI=www.microsoft.com
volumes:
- ./snell-config:/etc/snellCommon commands:
docker compose up -d # start
docker compose logs snell-shadowtls # client config
docker compose down # stop and removeThe first container start (when the config is generated) prints a Surge-ready config to the log — no manual assembly. Later restarts don't print the PSK in plain text:
docker logs snell-server # started with docker run
docker compose logs snell-shadowtls # started with docker composeExample output:
==============================================================
Snell 客户端配置 (Surge 格式)
==============================================================
服务器 : 1.2.3.4
端口 : 8443
PSK : duBN4HXibFaJejO2LC61/A==
Snell 版本 : 5
ShadowTLS : v3, SNI = www.microsoft.com
ShadowTLS 密码 : vwiOI52JPMPYhpTA/n/BKQ==
Snell 后端端口 : 6160 (仅容器内监听)
--------------------------------------------------------------
Snell = snell, 1.2.3.4, 8443, psk = duBN4HXibFaJejO2LC61/A==, version = 5, reuse = true, tfo = true, shadow-tls-password = vwiOI52JPMPYhpTA/n/BKQ==, shadow-tls-sni = www.microsoft.com, shadow-tls-version = 3
--------------------------------------------------------------
The same content is written to the mounted volume:
cat ./snell-config/client-config.txt # client config
cat ./snell-config/snell-server.conf # server config
cat ./snell-config/shadowtls-password # ShadowTLS password
- The server address comes from an automatic public-IP probe; on failure a placeholder is printed — set
SNELL_SERVER_IPto override.- The port shown is the container's listening port; replace it if the host maps a different one.
- The first start's log contains the PSK and ShadowTLS password — do not share it publicly; later restarts don't log the PSK.
- You can always view the full client config with
docker exec <container> cat /etc/snell/client-config.txt.
Common
| Variable | Default | Description |
|---|---|---|
SNELL_VER |
follows image tag | Config mode: v4 / v5 / v6
|
SNELL_PORT |
6160 |
Snell listening port |
SNELL_PSK |
random | Snell PSK |
SNELL_LISTEN_HOST |
0.0.0.0 |
Listen address; use 127.0.0.1 with ShadowTLS |
SNELL_IPV6 |
true |
v4 option; mapped to dns-ip-preference on v6 (false → ipv4-only) |
SNELL_TFO |
true |
v4 option, not written for v5 / v6 |
Snell v6 only
| Variable | Default | Description |
|---|---|---|
SNELL_MODE |
default |
default / unshaped / unsafe-raw — must match the client
|
SNELL_DNS_IP_PREFERENCE |
follows SNELL_IPV6
|
default / prefer-ipv4 / prefer-ipv6 / ipv4-only / ipv6-only
|
SNELL_DNS |
unset | Custom DNS servers, comma-separated |
ShadowTLS
| Variable | Default | Description |
|---|---|---|
SHADOWTLS_ENABLE |
0 |
Set to 1 to enable ShadowTLS v3 |
SHADOWTLS_PORT |
8443 |
Public ShadowTLS port |
SHADOWTLS_PASSWORD |
random | Stored at /etc/snell/shadowtls-password
|
SHADOWTLS_SNI |
www.microsoft.com |
TLS camouflage SNI |
Client config output
| Variable | Default | Description |
|---|---|---|
SNELL_NODE_NAME |
Snell |
Node name in the printed config |
SNELL_SERVER_IP |
auto-probed | Server address (IP or domain) to print |
SNELL_IP_LOOKUP |
1 |
Set to 0 to skip the public-IP probe |