Sign inSign up

1byte/snell-server

By 1byte

•Updated 3 days ago

A lightweight, Busybox-based, multi-architecture(amd64 and arm64) Docker image for Snell Server.

Image
Networking
3

10K+

1byte/snell-server repository overview

English⁠ | 中文⁠

⁠Snell Server Docker Image

Build Release Image Size Docker Pulls Docker Stars FOSSA Status Repository License

A lightweight, multi-architecture (linux/i386, linux/amd64, linux/arm64 and linux/armv7l) Docker image for Snell Server.
Supports configuration via environment variables, with secure defaults when not provided: random PSK and random port (>1024).

⁠Available Images

This project provides Docker images from two sources:

  • Docker Hub: 1byte/snell-server
  • GitHub Container Registry (GHCR): ghcr.io/waterdrops/snell-server

Both images are identical and you can use either one based on your preference.

⁠Features

  • Multi-stage build for a smaller image size
  • Multi-architecture support: linux/i386, linux/amd64, linux/arm64 and linux/armv7l
  • Configurable via environment variables
  • Secure defaults: random port and random 32-character PSK
  • Minimal dependencies: based on debian:stable-slim⁠ and busybox:stable⁠
  • Conditional configuration: only writes optional fields when values are provided
  • Input validation: validates IPv6, MODE, DNS_IP_PREFERENCE, and OBFS values before startup

⁠Environment Variables

VariableDefault ValueDescriptionValidation Rules
PORTRandom 1025–65535Listening portMust be integer 1025–65535
PSKRandom 32-char alphanumericPre-shared keyRequired
LISTEN0.0.0.0:PORTListen addressesWhen IPv6=true, set to 0.0.0.0:PORT,[::]:PORT; override with a custom value when IPv6 is not true
DNS_IP_PREFERENCEdefaultDNS IP family preferenceMust be default, prefer-ipv4, prefer-ipv6, ipv4-only, or ipv6-only
IPv6Not set (optional)Enable IPv6Must be true or false if provided
MODENot set (optional)Snell v6 crypto/obfuscation mode (beta 3+)Must be default, unshaped, or unsafe-raw if provided
OBFSNot set (optional)Obfuscation mode (legacy)Must be off or http if provided
OBFS_HOSTNot set (optional)Obfuscation hostOnly used when OBFS=http
TFOtrueEnable TCP Fast OpenBoolean

⁠Configuration Behavior

The server uses conditional configuration writing:

  • IPv6: Only written to config if IPv6 environment variable is set; when IPv6=true, listen is set to 0.0.0.0:PORT,[::]:PORT for dual-stack binding
  • LISTEN: Written to config as listen; defaults to 0.0.0.0:PORT, or dual-stack when IPv6=true
  • DNS_IP_PREFERENCE: Always written to config as dns-ip-preference (default: default)
  • MODE: Only written to config if MODE environment variable is set
  • OBFS: Only written to config if OBFS environment variable is set
  • OBFS_HOST: Only written to config if OBFS=http and OBFS_HOST is set
  • Existing config file: If snell-server.conf already exists (e.g., mounted via volume), it will be used as-is and the script will skip generating a new one

⁠Docker Images

Published tags (example for Snell 6.0.0b3):

TagDescription
latestLatest build from main
6Latest image for Snell v6
6.0.0b3Exact Snell version (no v prefix)
# Docker Hub
docker pull 1byte/snell-server
docker pull 1byte/snell-server:6
docker pull 1byte/snell-server:6.0.0b3

# GitHub Container Registry
docker pull ghcr.io/waterdrops/snell-server
docker pull ghcr.io/waterdrops/snell-server:6
docker pull ghcr.io/waterdrops/snell-server:6.0.0b3

⁠Build the Image

⁠Local build:
# Build with default Snell version (5.0.1)
git clone https://github.com/waterdrops/snell-server-docker.git
cd snell-server-docker
docker build -t 1byte/snell-server .

# Build with specific Snell version
docker build --build-arg SNELL_VERSION=4.1.1 -t 1byte/snell-server:4.1.1 .
⁠Multi-arch build (requires buildx):
# Build with default Snell version (5.0.1)
cd snell-server-docker # Please make sure to clone it first before proceeding
docker buildx build \
  --platform linux/amd64,linux/arm64 \
  -t 1byte/snell-server:latest .

# Build with specific Snell version
docker buildx build \
  --platform linux/amd64,linux/arm64 \
  --build-arg SNELL_VERSION=4.1.1 \
  -t 1byte/snell-server:v4.1.1 .

⁠Run Examples

⁠Default config (random port & PSK, for testing only)
# Using Docker Hub
docker run --stop-timeout 2 --rm 1byte/snell-server

# Using GitHub Container Registry
docker run --stop-timeout 2 --rm ghcr.io/waterdrops/snell-server
⁠Specify port and PSK
# Using Docker Hub
docker run -it -p 8234:8234 \
  --stop-timeout 2 \
  -e PORT=8234 \
  -e PSK=mysecurepsk \
  1byte/snell-server

# Using GitHub Container Registry
docker run -it -p 8234:8234 \
  --stop-timeout 2 \
  -e PORT=8234 \
  -e PSK=mysecurepsk \
  ghcr.io/waterdrops/snell-server
⁠Complete configuration example

Please refer to the Environment Variables section and adjust them as needed. For example, set MODE=unshaped for higher throughput (client must use the same mode).

# Using Docker Hub
docker run -itd -p 8234:8234 \
  --stop-timeout 2 \
  -e PORT=8234 \
  -e PSK=mysecurepsk \
  -e MODE=default \
  -e DNS_IP_PREFERENCE=default \
  -e IPv6=true \
  -e TFO=false \
  1byte/snell-server

# Using GitHub Container Registry
docker run -itd -p 8234:8234 \
  --stop-timeout 2 \
  -e PORT=8234 \
  -e PSK=mysecurepsk \
  -e MODE=default \
  -e DNS_IP_PREFERENCE=default \
  -e IPv6=true \
  -e TFO=false \
  ghcr.io/waterdrops/snell-server

⁠Run with docker-compose

⁠Quick start
  1. Ensure docker-compose.yml is in your working directory
  2. Provide environment variables via a .env file (recommended) or your shell
⁠Example .env and docker-compose.yml(place next to docker-compose.yml):
⁠.env
PORT=8234
PSK=mysecurepsk
# IPv6=false
# TFO=true
# dns-ip-preference = default # default | prefer-ipv4 | prefer-ipv6 | ipv4-only | ipv6-only
# MODE=default          # default | unshaped | unsafe-raw
# OBFS=http
# OBFS_HOST=gateway.icloud.com
⁠docker-compose.yml
services:
  snell-server:
    container_name: snell-server
    stop_grace_period: 2s
    restart: always
    image: 1byte/snell-server:latest
    ports:
      - "${PORT:-8234}:${PORT:-8234}"   # Default to 8234 if PORT is not set
    environment:
      PORT: "${PORT}"
      PSK: "${PSK}"
      # IPv6: "${IPv6}"
      # TFO: "${TFO}"
      # dns-ip-preference = default # default | prefer-ipv4 | prefer-ipv6 | ipv4-only | ipv6-only
      # MODE: "${MODE}"      # default | unshaped | unsafe-raw
      # OBFS: "${OBFS}"        # Set to "false" to disable; `http` enables it
      # OBFS_HOST: "${OBFS_HOST}"
    # volumes:
    #   - ./snell-server.conf:/app/snell-server.conf
⁠Use a custom snell-server.conf

If you already have a snell-server.conf, mount it and the script will skip auto-generation:

services:
  snell-server:
    # ...
    volumes:
      - ./snell-server.conf:/app/snell-server.conf

With this volume mount, the container will use your provided config file and ignore environment variables for generation.

⁠Start the service:
docker compose up -d
⁠Surge Client-Side Settings(iOS & macOS)
⁠Prerequisites
  • Apply for a public IP address from your ISP
  • Port mapping
  • Optional: A domain and a DNS provider(e.g, Cloudflare, AliCloud). If you are going to use a DNS provider and your IP is dynamic, I recommend ddns-go for automatic DNS updates. It's a simple and easy-to-use DDNS tool. See 3⁠ for more details.

Add the following to your Surge configuration file (e.g, Surge.conf), and replace placeholders like YOUR_FQDN, YOUR_PUBLIC_IP, YOUR_DOMAIN, ${PORT}, ${PSK}, MyHome and IP-CIDR,192.168.188.0/24 with your actual values.

To learn more about Surge Policy Groups, see Surge Policy Group documentation1⁠ and Surge Manual2⁠. For more information on Snell, refer to Snell knowledge4⁠.

[Proxy]
home = snell, YOUR_FQDN or YOUR_PUBLIC_IP, ${PORT}, psk=${PSK}, version=6, reuse=true
# mode=unshaped for higher throughput (must match server MODE):
# home = snell, YOUR_PUBLIC_IP or YOUR_FQDN, YOUR_PORT, psk=YOUR_PSK, version=6, mode=unshaped, reuse=true, tfo=true
...
[Proxy Group]
# Define a policy group named `🏠Home` of type `subnet`.  
# Behavior: If the current Wi-Fi SSID is `MyHome`, connect directly;  
# otherwise, switch to the `🏠Home` policy group.
# Please refer to [1] for more details.
🏠Home = subnet, default = home, SSID:MyHome = DIRECT
...
[Rule]
IP-CIDR,192.168.188.0/24,🏠Home,no-resolve
# Modify the following line as needed when using DNS(e.g, Cloudflare or another provider.)
OR,((DOMAIN,plex.YOUR_DOMAIN), (DOMAIN,vw.YOUR_DOMAIN), (DOMAIN,gitea.YOUR_DOMAIN), (DOMAIN,myns.YOUR_DOMAIN)),🏠Home
...

⁠Error Handling

The server validates all input values before starting:

  • Invalid PORT: Must be an integer between 1025 and 65535
  • Invalid IPv6: Must be true or false if provided
  • Invalid DNS_IP_PREFERENCE: Must be default, prefer-ipv4, prefer-ipv6, ipv4-only, or ipv6-only
  • Invalid MODE: Must be default, unshaped, or unsafe-raw if provided
  • Invalid OBFS: Must be off or http if provided

If any validation fails, the server will display an error message and exit with code 1.

⁠License

LICENSE⁠

FOSSA Status

Tag summary

Content type

Image

Digest

sha256:6778d8c61…

Size

6.7 MB

Last updated

3 days ago

docker pull 1byte/snell-server