In this tutorial you’ll learn how to create your own Shadowsocks server on an Ubuntu 20.04 platform using Docker.
The server you’ll build will implement the authenticated encryption with associated data (AEAD) cipher
chacha20-ietf-poly1305. You’ll test your server with the Shadowsocks for Windows graphical user interface (GUI) client.
At the end of this tutorial, you’ll have a working and tested Shadowsocks server.
Before you begin this tutorial, you will need a virtual private server (VPS) running Ubuntu 20.04. You can rent servers from companies such as Vultr or Bandwagon Host. You do not need a domain name for the server in this tutorial.
Step 1 — Logging In as Root
SSH into your server. On Linux and macOS, you can use the terminal command
ssh to reach your server. On Windows, you can either use PowerShell or a graphical user interface (GUI) such as PuTTY or XSHELL.
If you’re not logged in as
root, then become
root as follows. If you don’t already know the root password, then set it by issuing the command:
sudo passwd root
sudo command allows non-root users to issue root commands. The
passwd command allows you to set the password for yourself or another user, which in this case is the user named
You are prompted to enter your own password:
[sudo] password for amy:
Enter your own (non-root) password.
You are then prompted to enter a new password for the user
Choose and enter the new password for
You are prompted to confirm the new password by retyping it:
Retype new password:
Enter the same new password for
If all is well, you will receive a feedback message:
passwd: password updated successfully
Now you know the root password, become
su command (short for switch user) allows you to switch to another user id, so that you can run commands with that user’s privileges. Since no specific user is named, you will by default switch to the user
root. The hyphen (
-) means create a new login environment for the new user, which will be completely separate from your existing login environment.
You are prompted to enter the password for
root that you set a few moments ago:
Enter the root password.
You will notice that your command prompt changes from a dollar sign to a hash sign:
This is a reminder that your are logged in as
root. Now that you are
root, you do not need to prefix privileged commands with
Update your package lists, and upgrade all your packages to the latest version:
apt update && apt upgrade -y
You will see package upgrade messages in your terminal.
Step 2 — Generating a Random Port Number
Your Shadowsocks server will use a random port for its input. Generate a random number between 1024 and 65535 for your Shadowsocks port number.
shuf -i 1024-65535 -n 1
shuf command generates random permutations.
-i specifies an input range, and
-n is the number of lines of output required. We will use the following example in the rest of this tutorial:
Make a note of this number, as you will need it on both the server and the client.
Step 3 — Enabling the Firewall (Optional)
We recommend that you protect your server and especially port
22 (the SSH port) by installing a firewall. In this tutorial, you’ll install and configure the uncomplicated firewall (
On many Ubuntu systems,
ufw is already installed. Check that
ufw is installed on your system:
apt list ufw
You should see a message:
ufw/focal,now 0.36-6 all [installed]
If you do not see the message stating that
ufw is already installed, then install the software package now:
apt install ufw
Now you’ll set up the firewall. If you can guarantee that you will always SSH into your server from a single IP address, then limit SSH access to just that single address. For example, if your IP address is
188.8.131.52, then issue the command:
ufw allow from 184.108.40.206/32 to any port 22 proto tcp
When you execute that command, you will see a message:
If limiting access to a single IP address is not possible, but you can guarantee you will always connect from a known IP address range, then limit SSH access to just that range. For example, if you are in an office which always uses the IP address range
220.127.116.11/24, then issue the command:
ufw allow from 18.104.22.168/24 to any port 22 proto tcp
If limiting access to an IP address range is not possible, then you will have to open the SSH port for access from the entire world:
ufw allow ssh
In any case, we recommend that you further protect port
22 by using SSH key authentication in preference to password authentication. SSH key pair generation and upload to your server are out of scope for this tutorial. You can find tutorials on this subject on the web.
Open your Shadowsocks port, which in our example is
ufw allow 25117/tcp
ufw allow 25117/udp
You will see a warning message:
Command may disrupt existing ssh connections. Proceed with operation (y|n)?
Y and press
ENTER to confirm that you wish to enable
ufw. You will see a message:
Firewall is active and enabled on system startup
Check the status of your firewall:
You will see a firewall status display that looks like the following:
To Action From
-- ------ ----
22/tcp ALLOW 22.214.171.124/24
25117/tcp ALLOW Anywhere
25117/udp ALLOW Anywhere
25117/tcp (v6) ALLOW Anywhere (v6)
25117/udp (v6) ALLOW Anywhere (v6)
If your VPS provider implements the concept of security groups, you will also need to open your security group assignments for these posrts in your provider’s control panel.
Step 4 — Generating a Strong Password
You need to generate a strong password to protect your server. Copy and paste the following command into your terminal session with your server:
< /dev/urandom tr -dc A-Za-z0-9 | head -c 16; echo;
The special file
/dev/urandom on Linux systems provides an interface to the kernel’s pseudorandom number generator. The contents of
/dev/urandom become input to
tr command is a command-line utility for translating or deleting characters.
-d means delete and
-c means complement, so
-dc means delete any characters that are not in the set
The output, now alphanumeric only, is piped into
head command is a command-line utility for outputting the first part of a file given to it via standard input. The
-c switch limits the number of characters. The operand
16 is the number of characters you want.
echo command echoes back input to the terminal, which in this case just gives you a new line after the display of your password.
Here is the sample output. You will see this example used in the rest of this tutorial:
Copy your generated password. Open a text editor on your PC . Paste the password into your text editor.
You will need this password on both your server and your client when you run Shadowsocks.
Step 5 — Installing Docker
Now you’ll install Docker on your server.
Install packages to allow
apt to use a repository over HTTPS:
apt install -y apt-transport-https ca-certificates curl gnupg lsb-release
Add Docker’s official GPG key:
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
Use the following command to set up the Docker stable repository:
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
/etc/apt/sources.list.d/docker.list now contains the Docker repository. Update your package lists accordingly:
apt install -y docker-ce docker-ce-cli containerd.io
Verify that Docker Engine is installed correctly by running the
docker run hello-world
You should see messages:
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
b8dfde127a29: Pull complete
Status: Downloaded newer image for hello-world:latest
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
For more examples and ideas, visit:
Step 6 — Pulling the Image
Pull Teddysun’s Docker image for Shadowsocks-Rust by issuing the command:
docker pull teddysun/shadowsocks-rust
You will see messages that look like the following:
Using default tag: latest
latest: Pulling from teddysun/shadowsocks-rust
45b42c59be33: Pull complete
f50629ee3cc4: Pull complete
b270b750cfe4: Pull complete
3854afaafaf8: Pull complete
0cc26c8d335f: Pull complete
c02c65108591: Pull complete
Status: Downloaded newer image for teddysun/shadowsocks-rust:latest
Step 7 — Configuring Shadowsocks
Now you’ll create your Shadowsocks configuration file on the server.
Make a directory in
Create a configuration file
/etc/shadowsocks-rust/config.json using the example below as a template. Before you use the example:
25117by your choice of random port number
25u4kC4XbIWZJ75Qby your choice of strong password
chacha20-ietf-poly1305by your choice of cipher, but make sure you use an AEAD cipher
cat > /etc/shadowsocks-rust/config.json <<EOF
Step 8 — Running the Container
Run the command that follows, replacing
25117 in all four places by your choice of port number:
docker run -d -p 25117:25117 -p 25117:25117/udp --name ss-rust --restart=always -v /etc/shadowsocks-rust:/etc/shadowsocks-rust teddysun/shadowsocks-rust
-d option means run detached. The
-p option specifies exposed ports. The
-v option gives the volumes.
Step 9 — Testing with Windows Client
Now work on your PC.
Download the most recent release of the Windows client from https://github.com/shadowsocks/shadowsocks-windows/releases.
Double-click on the application
shadowsocks.exe to launch the Shadowsocks for Windows client. If Microsoft Defender SmartScreen appears, click More info then Run anyway.
Enter client parameters that match the configuration you specified on your server:
- Enter your actual Server IP address
- Enter your choice of Shadowsocks Server Port number, which is
25117in our example
- Enter your choice of Password, which is
25u4kC4XbIWZJ75Qin our example
- Select your choice of Encryption cipher, which is
chacha20-ietf-poly1305in our example
Click OK. A notification appears to say that Shadowsocks is connected.
Right-click on the Shadowsocks paper airplane icon in the system tray. This brings up the context menu. Select System Proxy. Make sure you are in Global mode.
In your browser, visit https://www.iplocation.net to confirm that your web browsing is now coming from your server location.
When you have finished browsing, Quit Shadowsocks from the context menu.
You now have a working Shadowsocks server that you’ve tested with the Windows client.
You can find out more about the different versions of Shadowsocks at https://github.com/shadowsocks.
- How to Create a VLESS WebSocket TLS CDN Server on Ubuntu 20.04
- How to Create a Brook Server and Client on Ubuntu 20.04
- How to Install Tor Browser or Standalone Tor on Ubuntu 20.04
- How to Build a Camouflaged Telegram MTProto Proxy Server on Ubuntu 20.04
- How to Build a V2Ray Tor On-Ramp on Ubuntu 20.04