Setting up a Shadowsocks Server on Linux

If you’ve found this post, you probably don’t need me to tell you what Shadowsocks is or what it is for. You can read all about shadowsocks or shadowsocks-libev here.

Before we get started, make sure you have a Linux server running. I’m using a Vultr LA server. Linode is great too.

Basic Setup

Install shadowsocks-libev

First, clone the shadowsocks-libev repo:

git clone [email protected]:shadowsocks/shadowsocks-libev.git

Then, install the dependencies depending on your Linux flavor:

# Installation of basic build dependencies
## Debian / Ubuntu
sudo apt-get install --no-install-recommends gettext build-essential autoconf libtool libpcre3-dev asciidoc xmlto libev-dev libc-ares-dev automake libmbedtls-dev libsodium-dev
## CentOS / Fedora / RHEL
sudo yum install gettext gcc autoconf libtool automake make asciidoc xmlto c-ares-devel libev-devel
## Arch
sudo pacman -S gettext gcc autoconf libtool automake make asciidoc xmlto c-ares libev

Finally, install shadowsocks-libev:

# Installation of libsodium
export LIBSODIUM_VER=1.0.16
tar xvf libsodium-$LIBSODIUM_VER.tar.gz
pushd libsodium-$LIBSODIUM_VER
./configure --prefix=/usr && make
sudo make install
sudo ldconfig
# Installation of MbedTLS
export MBEDTLS_VER=2.6.0
tar xvf mbedtls-$MBEDTLS_VER-gpl.tgz
pushd mbedtls-$MBEDTLS_VER
make SHARED=1 CFLAGS="-O2 -fPIC"
sudo make DESTDIR=/usr install
sudo ldconfig
# Start building
git submodule init && git submodule update
./ && ./configure && make
sudo make install

Option 2: with Snap

Snap is shipped with most modern OS, so it you are on Debian 9+, CenOS 7.6+, Ubuntu 16.04 LTS or later, just run

sudo snap install shadowsocks-libev

If you’re on older software, follow to install snap core first, then run the above.


sudo vim /etc/shadowsocks-libev/config.json
# For Debian:
sudo vim /etc/default/shadowsocks-libev

"server": ["[::0]", ""], # alternatively, use your actual ipv6, ipv4 addresses
"server_port": "<YOUR CUSTOM PORT>",
"mode": "tcp_and_udp",
"password": "<YOUR STRONG PASSWORD>",
"timeout": 300,
"method": "aes-256-gcm"

Advanced Setups


BBR (Bottleneck Bandwidth and Round-trip propagation Time) is latest and greatest from Google for TCP congestion control.

To put it simply, it’s the magic dust for juicing every last drop of your server network Google made open-source. Sweet, right?

Hey Linode users! Right now would be a good time to go and upgrade your kernel before moving on with the rest of the tutorial. Check out the last section of this post for how to do that.

Make sure you are root and run the following:

wget --no-check-certificate
chmod +x

When you’re done, reboot the server.

Then, check if we’re all set:

sysctl net.ipv4.tcp_available_congestion_control | grep -q 'bbr' && echo '1 Yes'; sysctl net.ipv4.tcp_congestion_control | grep -q 'bbr' && echo '2 Yes'; sysctl net.core.default_qdisc | grep -q 'fq' && echo '3 Yes'; lsmod | grep bbr | grep -q 'tcp_bbr' && echo '4 Yes'

If you don’t see four yes’s, run the following

echo "net.core.default_qdisc = fq" >> /etc/sysctl.conf
echo "net.ipv4.tcp_congestion_control = bbr" >> /etc/sysctl.conf


git clone
cd simple-obfs
git submodule update --init --recursive
./ && ./configure && make
sudo make install

Create a systemd service

sudo vim /etc/systemd/system/shadowsocks-libev.service

Description=Shadowsocks-libev Default Server Service
ExecStart=/usr/local/bin/ss-server -c /etc/shadowsocks-libev/config.json
# ExecStart=/usr/bin/ss-server -c $CONFFILE $DAEMON_ARGS

systemctl daemon-reload
systemctl start shadowsocks-libev
systemctl enable shadowsocks-libev

Cron Job for Periodic Restarts

This is optional. It won’t make nearly as much of a different to speed as BBR would, but setting up a cron job that restarts the server every now and then may just prevent it from getting sluggish.

First, create a shell script. I usually put it under /root/

systemctl restart shadowsocks-libev
systemctl status shadowsocks-libev

After that, let’s set up the cron job.

crontab -e

Append as the last line:

0 0 * * * bash /root/ >> /root/ss-libev-cron.log

Perfect. Let’s restart the cron service and we’re good to go.

service cron restart

Multiple Users

If you want to have multiple users, use the following template for your config.json.

"server": ["[::0]", ""],
"local_address": "",
"local_port": 1080,
"port_password": {
"<port-1>": "<port-1-password>",
"<port-2>": "<port-2-password>"
"timeout": 300,
"method": "aes-256-gcm",
"fast_open": true


Upgrading your Linux kernel (For Linode Users)

First, check your kernel information with:

uname -r

If it returns anything 4.9 and above, you are good to go. But for this instance 4.11+ actually works slightly better with BBR, so I’m still going to show you how kernel upgrade is done with Linode.

Install the Latest kernel

Go to to locate the latest linux image. Hint: look for the one that has linux-image and generic in it.

  1. Download the latest kernel:


  1. Install kernel:

dpkg -i linux-image-4.11.5*.deb

  1. Checking if installation is complete:

ls /boot/vmlinuz*

Incidentally, I didn’t purge the old kernel for safety concerns…

Configure GRUB

If you don’t have GRUB installed yet:

apt-get install linux-image-virtual grub2

  1. Edit /etc/default/grub and change the parameters to the following:

GRUB_CMDLINE_LINUX =“console = ttyS0,19200n8”
GRUB_SERIAL_COMMAND =“serial --speed = 19200 --unit = 0 --word = 8 --parity = no --stop = 1”

Keep everything else as it is.

  1. Update GRUB


  1. Under the “Boot Settings” of your linode, change kernel to “Grub 2”

  2. Reboot your Linode