Knowledgebase Simple instructions to work with the Profitserver service
Main Knowledgebase Shadowsocks Guide (shadowsocks-rust / shadowsocks-libev): VPS, Windows, macOS, Linux, Android, iPhone

Shadowsocks Guide (shadowsocks-rust / shadowsocks-libev): VPS, Windows, macOS, Linux, Android, iPhone


Shadowsocks is a lightweight, SOCKS5-based encrypted proxy protocol originally designed to get around traffic-shaping and blocking on ordinary networks. Unlike a full VPN, it only proxies the traffic an application explicitly sends to it, has almost no protocol overhead, and works well even on constrained connections. It doesn't try to mimic a real TLS handshake the way VLESS+Reality does — its strength is simplicity, wide client support (routers, phones, browsers), and very low latency, at the cost of being somewhat easier to fingerprint by traffic pattern on a heavily inspected network.

There are two actively maintained server implementations:

  • shadowsocks-rust — the modern reference implementation from the shadowsocks organization, written in Rust. It supports the newer AEAD-2022 cipher family, is actively developed, and is the implementation this guide installs and configures in detail.
  • shadowsocks-libev — the older C implementation. It's still maintained for bug fixes, ships as a ready-made apt package with its own systemd units, and is a good choice if you want the absolute simplest install with no manual binary handling. This guide covers it as an alternative installation path in Section 3.

This guide describes how to manually configure the server via the command line—without using a web panel or Docker. Wherever the "IP address" field appears, substitute it with your VPS's actual IP address.

What you'll need: a VPS running Ubuntu 22.04/24.04 or Debian 11/12, root access, your VPS's IP address, and a free UDP/TCP port (this guide uses 8388, the Shadowsocks default).

Don't have a server yet? See How to order a server and pay for it.

Comparing this against other self-hosted options first? See Xray VLESS Reality Guide for a TLS-camouflage-based alternative, AmneziaWG Server Deployment Guide for a WireGuard-based option, or Hysteria2 and TUIC setup for two other modern proxy protocols.

Connecting to the Server

Windows (PuTTY)

Open PuTTY, enter your VPS IP address in the Host Name field, set the port to 22, and log in as root using the password your VPS provider emailed you.

Server IP address: your IP address

login as: root

Password: your password

For a detailed walkthrough of connecting via PuTTY/SSH, see How to connect to a Linux server through SSH.

1_1 2_1 3_1

Linux / macOS (terminal)

ssh root@your_IP_address

All commands below are run on the server, in this same SSH session — that covers Sections 2 through 7, plus the server-side checks in Section 13. Sections 8–12 (installing and configuring the client apps) happen on your own Windows/macOS/Linux/Android/iOS device instead, since that's the device the proxy needs to run on; each of those sections says explicitly which lines, if any, still touch the server.

Preparing the Server

Update the system

Before installing anything, refresh the package list and upgrade installed packages:

apt update -y && apt upgrade -y
4_1 5_1 6_1 7_1

If this upgrades the kernel, a reboot is a good idea before continuing. (For a refresher on apt and how Linux package managers work, see Linux Package Managers.) Check with:

cat /var/run/reboot-required
8_1 9_1

If the file exists, reboot first with 'reboot', wait ~30 seconds, then reconnect.

Install the tools this guide uses

apt install -y curl wget tar xz-utils ufw qrencode

curl/wget and tar/xz-utils are needed to fetch and unpack the shadowsocks-rust release archive; ufw is the firewall configured below; qrencode turns the finished client link into a scannable QR code in Section 7.

10_1

Configure the firewall (UFW)

For more on UFW rules, see Configuring Firewall on Linux.

Open the two ports you'll need: 22/tcp for SSH (skip this rule and you risk losing access to the server) and 8388, both tcp and udp — Shadowsocks proxies both TCP connections and UDP associations (useful for DNS and some games/apps), so both directions of the port must be open.

ufw allow 22/tcp
ufw allow 8388/tcp
ufw allow 8388/udp
ufw --force enable
ufw status

All three rules should show as ALLOW in the ufw status output. If you later change the port in config.json, update these rules to match.

11_1

Installing the Server Software

Pick one of the two options below. Option A (shadowsocks-rust) is recommended: it's the actively developed implementation and supports the modern AEAD-2022 ciphers used later in this guide. Option B (shadowsocks-libev) is a fine choice if you'd rather use a plain apt package with a ready-made systemd unit and don't need AEAD-2022.

Option A — shadowsocks-rust (recommended)

Shadowsocks-rust doesn't ship an apt package with current releases, so it's installed by downloading the prebuilt static binary from the project's GitHub releases. Fetch the latest release tag from the GitHub API and download the matching Linux x86_64 archive:

SS_VER=$(curl -s https://api.github.com/repos/shadowsocks/shadowsocks-rust/releases/latest | grep -Po '"tag_name": "\K[^"]*')
echo "Latest version: $SS_VER"
cd /root
wget "https://github.com/shadowsocks/shadowsocks-rust/releases/download/${SS_VER}/shadowsocks-${SS_VER}.x86_64-unknown-linux-gnu.tar.xz"
12_1

If your VPS is arm64 instead of x86_64 (check with `uname -m`), replace x86_64-unknown-linux-gnu with aarch64-unknown-linux-gnu in the filename above.

Extract the archive and install the binaries system-wide:

tar -xf shadowsocks-*.tar.xz
install -m 755 ssserver ssservice ssmanager ssurl /usr/local/bin/
rm -f shadowsocks-*.tar.xz ssserver ssservice ssmanager ssurl sslocal 2>/dev/null
13_1

Verify the binary is in place and check the installed version:

ssserver --version
14_1

Create the directory the configuration file will live in:

mkdir -p /etc/shadowsocks-rust
15_1

This guide installs a fixed version rather than piping an installer script into bash. To upgrade later, re-run the two commands above with a fresh SS_VER lookup, stop the service, replace the binary, and restart it (Section 6).

Option B — shadowsocks-libev (alternative, apt package)

Shadowsocks-libev is included in Ubuntu's universe repository (Ubuntu 16.10+) and Debian's main repository (Debian 8+), so no third-party PPA is needed on 22.04/24.04 or Debian 11/12:

apt install -y shadowsocks-libev
16_1

If apt reports the package isn't found, the universe repository is disabled; enable it and retry:

add-apt-repository universe && apt update && apt install -y shadowsocks-libev

The package installs its own systemd units (shadowsocks-libev.service for the default config, plus [email protected] for named per-instance configs) and creates /etc/shadowsocks-libev/config.json automatically — Sections 4–6 note the libev-specific commands and file paths alongside the rust ones. The rest of this guide's client sections (7–13) apply identically to either server implementation, since both speak the same Shadowsocks/SIP002 protocol on the wire.

Generating the Password and Choosing a Cipher

Shadowsocks authentication is a single shared password plus a cipher (encryption method) that both sides must agree on — there's no separate UUID, key pair, or certificate to manage.

Cipher families

  • AEAD-2022 (recommended, shadowsocks-rust only): 2022-blake3-aes-128-gcm, 2022-blake3-aes-256-gcm, 2022-blake3-chacha20-poly1305. Newer design (SIP022) with stronger replay protection and support for multiple users sharing one port. The password must be a base64 string of exactly the cipher's key length (16 bytes for the 128-bit variants, 32 bytes for the 256-bit variant).
  • Classic AEAD (supported by both rust and libev): aes-256-gcm, aes-128-gcm, chacha20-ietf-poly1305. Widely compatible with older clients and with shadowsocks-libev; the password can be any passphrase, since it's fed through a key-derivation function rather than used directly as key material.

This guide uses 2022-blake3-aes-256-gcm for the shadowsocks-rust server, since it's the strongest and most current option and every client recommended later (v2rayN, v2rayNG, Shadowrocket, Streisand, ShadowsocksX-NG) supports it. If you installed shadowsocks-libev in Section 3, use chacha20-ietf-poly1305 or aes-256-gcm instead, since libev does not implement AEAD-2022.

Generate a key (shadowsocks-rust)

ssservice genkey -m "2022-blake3-aes-256-gcm"
17_1

This prints a base64 string — that's your password. Copy it somewhere safe; you'll paste it into both the server configuration in Section 5 and the client link in Section 7.

18_1

Choose a passphrase (shadowsocks-libev)

For the classic AEAD ciphers used by shadowsocks-libev, any sufficiently long random string works, since it's run through PBKDF/HKDF rather than used as a raw key. Generate one with:

openssl rand -base64 32

Writing the Server Configuration

Shadowsocks-rust

Open the configuration file for editing:

nano /etc/shadowsocks-rust/config.json

Paste in the template below, substituting your own password from Section 4 (and the port from Section 2, if you changed it from 8388):

{
    "server": "0.0.0.0",
    "server_port": 8388,
    "password": "YOUR-GENERATED-KEY-HERE",
    "method": "2022-blake3-aes-256-gcm",
    "mode": "tcp_and_udp",
    "timeout": 300,
    "nofile": 51200
}

Press Ctrl+O (WriteOut) to save the file, Enter to confirm the file name, then Ctrl+X to exit nano.

The important fields: server listens on all interfaces (0.0.0.0); server_port is the port opened in Section 2; password/method are the credential and cipher from Section 4; mode enables both TCP and UDP relaying; timeout is the idle-connection timeout in seconds; nofile raises the file-descriptor limit for busy servers.

Validate the JSON and that the binary accepts it before wiring it into systemd:

ssserver -c /etc/shadowsocks-rust/config.json --help >/dev/null && echo "binary OK"
python3 -m json.tool /etc/shadowsocks-rust/config.json >/dev/null && echo "JSON OK"

Create the systemd unit (shadowsocks-rust)

The binary release doesn't ship a systemd unit, so create one:

nano /etc/systemd/system/ssserver.service
[Unit]
Description=Shadowsocks-Rust Server
Documentation=https://github.com/shadowsocks/shadowsocks-rust
After=network.target
 
[Service]
Type=simple
ExecStart=/usr/local/bin/ssserver -c /etc/shadowsocks-rust/config.json
Restart=on-failure
RestartSec=5s
LimitNOFILE=51200
User=root
 
[Install]
WantedBy=multi-user.target

Save and exit as above, then tell systemd to pick up the new unit file:

systemctl daemon-reload

Shadowsocks-libev

The apt package already created /etc/shadowsocks-libev/config.json with a default (loopback-only, random password) configuration and its own systemd unit. Open it for editing:

19_1
nano /etc/shadowsocks-libev/config.json

Replace the contents with:

{
    "server":"0.0.0.0",
    "server_port":8388,
    "password":"YOUR-PASSPHRASE-HERE",
    "method":"chacha20-ietf-poly1305",
    "mode":"tcp_and_udp",
    "timeout":300
}
20_1

The default config uses server: ["::1", "127.0.0.1"] (loopback only); changing it to "0.0.0.0" is what makes the server reachable from the public IP — don't skip this if you copied the stock file instead of the template above.

Starting the Service and Enabling Autostart

Shadowsocks-rust

systemctl enable --now ssserver
systemctl status ssserver --no-pager

Status should show active (running). Confirm something is actually listening on the port (both protocols):

21_1
ss -lntp | grep ':8388'
ss -lunp | grep ':8388'

If the service fails to start, the fastest way to see why is the systemd journal (for background on reading Linux logs in general, see How to read Linux logs and where to find it):

journalctl -u ssserver -n 50 --no-pager

Shadowsocks-libev

systemctl restart shadowsocks-libev
systemctl enable shadowsocks-libev
systemctl status shadowsocks-libev --no-pager

Check the port and logs the same way as for shadowsocks-rust, substituting the service name:

22_1 23_1
ss -lntp | grep ':8388'
ss -lunp | grep ':8388'
journalctl -u shadowsocks-libev -n 50 --no-pager

Building the Client Connection Link

Shadowsocks clients import a single ss:// share link (the SIP002 URL format) rather than a config file. The link encodes the cipher and password as base64 in the userinfo portion of the URL:

ss://base64(method:password)@your_IP_address:port#label

Build the base64 portion on the server (this avoids any typos from hand-encoding):

METHOD="2022-blake3-aes-256-gcm"
PASSWORD="YOUR-GENERATED-KEY-HERE"
USERINFO=$(echo -n "${METHOD}:${PASSWORD}" | base64 -w0)
echo "ss://${USERINFO}@your_IP_address:8388#My-SS-Server"

Example output (with placeholder key):

24_1
ss://MjAyMi1ibGFrZTMtYWVzLTI1Ni1nY206eHl6X2V4YW1wbGVfa2V5X2hlcmU=@your_IP_address:8388#My-SS-Server

The text after # is just a display label you can rename freely in any client. For a shadowsocks-libev server, substitute METHOD="chacha20-ietf-poly1305" (or aes-256-gcm) and its passphrase from Section 4 instead. 

Turn it into a QR code so mobile clients can scan it directly:

qrencode -o ~/ss-client.png "ss://${USERINFO}@your_IP_address:8388#My-SS-Server"

Copy the PNG to your own computer with scp, run from your computer's terminal (or PowerShell on Windows), not the server:

scp root@your_IP_address:~/ss-client.png .

Connecting from Windows

Everything in this section happens on your Windows PC, not over SSH — the client has to run on the device that will actually use the proxy.

Install v2rayN

v2rayN is a free, actively maintained GUI client with native Shadowsocks support alongside VLESS, VMess, Trojan, and others. Download the latest release from the project's page. 

Grab the Windows 64-bit .zip asset (a self-contained build needs no separate .NET runtime as of recent v2rayN versions), extract it anywhere, and run v2rayN.exe.

Import the server

Copy the ss:// link built in Section 7 to your clipboard (or copy the QR PNG over with scp and open it), then in v2rayN choose Servers → Import bulk URL from clipboard (or scan the QR code via the built-in scanner). The new server profile appears in the list with the label you set after the #.

Right-click the profile and select it as active, then enable the system proxy (or TUN mode, for routing the whole machine) from the main window's toolbar.

Connecting from macOS

Everything in this section happens on your Mac, not over SSH.

Install ShadowsocksX-NG

ShadowsocksX-NG is the long-running native macOS GUI client for Shadowsocks; the current release line ships a native Apple Silicon build alongside Intel. Download the latest .dmg from the releases page.

Open the .dmg and drag ShadowsocksX-NG into Applications, then launch it — it appears as an icon in the menu bar.

 

Import the server

Copy the ss:// link from Section 7 to your clipboard, then click the menu-bar icon → Servers → Server Preferences → the + at the bottom-left, and choose "Import From Pasteboard" (or scan the QR code with "Scan QR Code From Screen" after opening the PNG). Select the new profile from the menu-bar dropdown, then toggle "Shadowsocks: On" and choose "PAC Auto" or "Global" routing mode from the same menu.

Connecting from a Linux Desktop

Everything in this section happens on your own Linux machine, not the VPS.

Install the local client

If you installed shadowsocks-rust on the server in Section 3, the same release archive contains sslocal, a SOCKS5/HTTP local proxy client. Download and install it the same way as the server binary (adjust the OS/arch suffix for your desktop if it isn't x86_64-unknown-linux-gnu):

SS_VER=$(curl -s https://api.github.com/repos/shadowsocks/shadowsocks-rust/releases/latest | grep -Po '"tag_name": "\K[^"]*')
wget "https://github.com/shadowsocks/shadowsocks-rust/releases/download/${SS_VER}/shadowsocks-${SS_VER}.x86_64-unknown-linux-gnu.tar.xz"
tar -xf shadowsocks-*.tar.xz
sudo install -m 755 sslocal /usr/local/bin/

Configure and run

Create a small local config listening on 127.0.0.1:1080 as a SOCKS5 proxy:

mkdir -p ~/.config/shadowsocks-rust
cat > ~/.config/shadowsocks-rust/local.json << 'EOF'
{
    "server": "your_IP_address",
    "server_port": 8388,
    "password": "YOUR-GENERATED-KEY-HERE",
    "method": "2022-blake3-aes-256-gcm",
    "local_address": "127.0.0.1",
    "local_port": 1080,
    "mode": "tcp_and_udp"
}
EOF
sslocal -c ~/.config/shadowsocks-rust/local.json

Point your browser or system network settings at a SOCKS5 proxy on 127.0.0.1:1080. For a GUI, Nekoray or ShadowsocksX-Qt5-style forks can import the same ss:// link from Section 7 and manage sslocal for you instead of running it by hand.

Connecting from Android

Everything here happens on your Android device, not over SSH.

Install a client

Two good options:

  • Shadowsocks for Android — the official client from the shadowsocks organization. Install it from Google Play (search "Shadowsocks"), or download the APK directly from the project's releases page if Play isn't available in your region.
  • v2rayNG — the Android counterpart to v2rayN, supporting Shadowsocks alongside VLESS/VMess/Trojan; useful if you want one app for multiple protocol types.

Import the server

In either app: tap the + button, choose "Import from clipboard" after copying the ss:// link from Section 7, or "Scan QR code" and point the camera at the PNG. Tap the imported profile to select it, then tap the connect button. Android will prompt for VPN permission the first time — approve it to establish the tunnel. 

Connecting from iOS

Everything here happens on your iPhone or iPad, not over SSH.

Install a Shadowsocks-capable client

Shadowrocket is the most widely used iOS client with Shadowsocks support; it's a paid app in most storefronts. Search for it in the App Store, or open.

Streisand is a free, open-source alternative that also supports Shadowsocks alongside VLESS, Trojan, and other protocols. 

App Store catalogs vary by storefront/region and can change over time; if neither is visible in yours, search the App Store for "Shadowsocks" or "V2Box".

Import the server

Copy the ss:// link to your clipboard, open the client, and use its Add/Import from clipboard option, or scan the QR code from Section 7 with the client's built-in scanner. Toggle the new profile on; iOS will prompt for VPN-configuration permission the first time, which you'll need to approve via Face ID, Touch ID, or your passcode.

Verifying the Connection

With the tunnel active from Section 8, 9, 10, 11, or 12, go back to your own device (not the SSH session) and open any "what's my IP" checker in a browser — the address shown should match your VPS's IP address, your_IP_address.

To verify from the server side instead, check the systemd journal for connection activity and confirm established sessions on the port (use ssserver for the rust journal, or shadowsocks-libev for the libev journal):

journalctl -u ssserver -n 50 --no-pager
ss -tnp | grep ':8388'

Reference:

Field

Value

Address

your VPS's public IP address

Port

8388 (the same port opened in Section 2)

Password

the key/passphrase generated in Section 4

Method

2022-blake3-aes-256-gcm (rust) or chacha20-ietf-poly1305 (libev) — must match exactly on both sides

Mode

tcp_and_udp — enables both TCP proxying and UDP relay (DNS, some games)

Plugin

none used in this guide — Shadowsocks needs no SNI, certificate, or transport plugin to function

Conclusion

Following this guide leaves your VPS running its own Shadowsocks server — either shadowsocks-rust with a modern AEAD-2022 cipher, or shadowsocks-libev from Ubuntu/Debian's own repository — as a systemd service that survives a reboot without any action on your part.

Adding more users:

  • Simplest: generate a second password (Section 4) and run a second ssserver/shadowsocks-libev instance on a different port with its own config file and systemd unit, then repeat Section 5–7 for that port.
  • shadowsocks-rust with an AEAD-2022 cipher also supports multiple users sharing one port and password-derivation key via the "users" array in config.json (Extensible Identity Headers, SIP022) — see the shadowsocks-rust README's Configuration section for the exact syntax if you need per-user traffic accounting on a single port.

A few habits worth keeping up once the server is running:

  • Keep the server updated. For shadowsocks-rust, periodically re-run the download-and-install steps from Section 3 with a fresh version lookup, then systemctl restart ssserver. For shadowsocks-libev, plain apt upgrade covers it.
  • Back up config.json somewhere private off the server. It holds every client's password; losing it means regenerating credentials for every device.
  • Rotate the password if a device is lost or a client is compromised: generate a new one (Section 4), update config.json, restart the service, and rebuild the client link (Section 7) for every remaining device.

If the connection won't come up, check in order:

  • the service status (systemctl status ssserver --no-pager, or shadowsocks-libev) and the journal (journalctl -u ssserver -n 50 --no-pager)
  • the firewall rules (ufw status — the port must be open for both tcp and udp)
  • that the port isn't already bound by another service (ss -lntp | grep ':8388' should show only ssserver/ss-server)
  • that the password, method, and port in the client match config.json exactly — a single mismatched character fails the handshake silently, usually showing as a connection timeout rather than an explicit error
  • that mode is set to tcp_and_udp on the server if the client needs UDP (DNS-over-proxy, some games/apps) and not just tcp_only

Comparing Shadowsocks against other options? See Xray VLESS Reality Guide for a TLS-camouflage-based protocol that's harder to fingerprint on a heavily filtered network, AmneziaWG Server Deployment Guide and How to set up Wireguard VPN on your server for WireGuard-based alternatives, or Hysteria2 and TUIC setup for two protocols built for lossy or heavily filtered networks. If you only need a simple proxy rather than a full tunneling setup, 3proxy configuration on CentOS/ArchLinuxis a much lighter alternative, and the older VPN server setup on Linux: PPTP or OpenVPN? covers protocols that are simpler to set up but far easier for DPI to detect and block. For general server hardening once the proxy is live, see Linux Users: Management and Permissions.


Ask us about VPS

We are always ready to answer your questions at any time of day or night.