outline-server/src/shadowbox
2025-12-08 07:10:55 -06:00
..
docker fix(server): fix version parsing (#1586) 2024-09-03 14:00:35 -04:00
infrastructure refactor(server): use a reusable http.Agent (#1644) 2025-02-21 16:15:14 -05:00
integration_test clean: add missing license headers and add a CI check (#1572) 2024-08-12 10:56:11 -04:00
model Add embedded OutlineCaddy integration and listener-aware WebSocket support 2025-10-08 20:05:02 -05:00
scripts feat(server): add an experimental opt-in API to enable ASN metrics (#1523) 2024-03-29 09:50:33 -04:00
server Switch Caddy configuration from JSON to YAML 2025-12-08 07:10:55 -06:00
types Fix lint 2022-03-09 23:10:15 +00:00
CHANGELOG.md Updates for 1.7.2 release (#1244) 2022-12-05 10:57:49 -05:00
package.json chore(server): inject version at build time (#1491) 2024-01-31 17:55:30 -05:00
README.md Add WebSocket support (SS over WSS) documentation and refactor manager service tests. 2025-12-04 03:53:22 -06:00
shadowbox_config.json Fix lint 2022-03-09 23:10:15 +00:00
Taskfile.yml Update caddy-l4 plugin version in Taskfile.yml 2025-12-02 22:39:10 -06:00
tsconfig.json chore: upgrade webpack to v5 to support lts/hydrogen (#1422) 2023-10-11 10:44:36 -04:00
webpack.config.js chore(server): inject version at build time (#1491) 2024-01-31 17:55:30 -05:00

Outline Server (Shadowbox)

The Outline Server, internal name "Shadowbox," is designed to streamline the setup and sharing of Shadowsocks servers. It includes a user management API and creates Shadowsocks instances when needed. It's managed by the Outline Manager and used as proxy by the Outline Client apps. Shadowbox is also compatible with standard Shadowsocks clients.

Installation

Self-Hosted Installation

  1. Run the Installation Script

    sudo bash -c "$(wget -qO- https://raw.githubusercontent.com/Jigsaw-Code/outline-apps/master/server_manager/install_scripts/install_server.sh)"
    
  2. Customize (Optional)

    Add flags for hostname, port, etc. Example:

    sudo bash -c "$(wget -qO- https://raw.githubusercontent.com/Jigsaw-Code/outline-apps/master/server_manager/install_scripts/install_server.sh)" install_server.sh \
      --hostname=myserver.com \
      --keys-port=443
    
    • Use sudo --preserve-env for environment variables.
    • Use bash -x for debugging.

Running from Source Code

Prerequisites

  • Docker
  • Node LTS (lts/hydrogen, version 18.16.0)
  • NPM (version 9.5.1)

Tip

If you use nvm, switch to the correct Node version with nvm use.

  1. Build and Run:

    Shadowbox supports running on linux and macOS hosts.

    • Node.js App

      task shadowbox:start
      
    • Docker Container

      task shadowbox:docker:start
      

      Tip

      Some useful commands when working with Docker images and containers:

      • Debug Image:

        docker run --rm -it --entrypoint=sh localhost/outline/shadowbox
        
      • Debug Running Container:

        docker exec -it shadowbox sh
        
      • Cleanup Dangling Images:

        docker rmi $(docker images -f dangling=true -q)
        
  2. Send a Test Request

    curl --insecure https://[::]:8081/TestApiPrefix/server
    

Access Keys Management API

The Outline Server provides a REST API for access key management. If you know the apiUrl of your Outline Server (e.g. https://1.2.3.4:1234/3pQ4jf6qSr5WVeMO0XOo4z), you can directly manage the server's access keys using HTTP requests:

  1. Find the Server's apiUrl:

    • Deployed with the Installation Script: Run grep "apiUrl" /opt/outline/access.txt | cut -d: -f 2-

    • Deployed with the Outline Manager: Check the "Settings" tab.

    • Local Deployments from Source: The apiUrl is simply https://[::]:8081/TestApiPrefix

  2. API Examples:

    Replace $API_URL with your actual apiUrl.

    • List access keys: curl --insecure $API_URL/access-keys/

    • Create an access key: curl --insecure -X POST $API_URL/access-keys

    • Get an access key (e.g. ID 1): curl --insecure $API_URL/access-keys/1

    • Rename an access key: curl --insecure -X PUT -F 'name=albion' $API_URL/access-keys/2/name

    • Remove an access key: curl --insecure -X DELETE $API_URL/access-keys/1

    • Set a data limit for all access keys: (e.g. limit outbound data transfer access keys to 1MB over 30 days) curl --insecure -X PUT -H "Content-Type: application/json" -d '{"limit": {"bytes": 1000}}' $API_URL/server/access-key-data-limit

    • Remove the access key data limit: curl --insecure -X DELETE $API_URL/server/access-key-data-limit

    • And more...

  3. Further Options:

    Consult the OpenAPI spec and documentation for more options.

WebSocket Support (SS over WSS)

The Outline Server supports Shadowsocks over WebSocket (SS over WSS) for improved censorship resistance. This tunnels Shadowsocks traffic over WebSocket connections, making it look like regular HTTPS web traffic.

Enabling WebSocket Support

  1. Configure Listeners for New Access Keys:

    Set up listener configuration including WebSocket paths:

    curl --insecure -X PUT -H "Content-Type: application/json" \
      -d '{
        "tcp": {"port": 443},
        "udp": {"port": 443},
        "websocketStream": {"path": "/tcp", "webServerPort": 8080},
        "websocketPacket": {"path": "/udp", "webServerPort": 8080}
      }' \
      $API_URL/server/listeners-for-new-access-keys
    
  2. Enable the Caddy Web Server (for automatic HTTPS):

    curl --insecure -X PUT -H "Content-Type: application/json" \
      -d '{
        "enabled": true,
        "autoHttps": true,
        "email": "admin@example.com",
        "domain": "your-domain.com"
      }' \
      $API_URL/server/web-server
    
  3. Create WebSocket-Enabled Access Keys:

    curl --insecure -X POST -H "Content-Type: application/json" \
      -d '{
        "name": "WebSocket User",
        "listeners": ["tcp", "udp", "websocket-stream", "websocket-packet"]
      }' \
      $API_URL/access-keys
    
  4. Get Dynamic Client Configuration:

    For WebSocket-enabled keys, retrieve the YAML configuration:

    curl --insecure $API_URL/access-keys/0/dynamic-config
    

Listener Types

  • tcp - Traditional TCP Shadowsocks
  • udp - Traditional UDP Shadowsocks
  • websocket-stream - TCP over WebSocket (for TCP traffic tunneling)
  • websocket-packet - UDP over WebSocket (for UDP traffic tunneling)

Note

WebSocket support requires a reverse proxy (like Caddy, Nginx, or Cloudflare Tunnel) in front of the internal WebSocket server port (default: 8080) to handle TLS termination and external traffic.

Testing

Manual

Build and run your image with:

task shadowbox:docker:start

Integration Test

The integration test will not only build and run your image, but also run a number of automated tests.

task shadowbox:integration_test

This does the following:

  • Sets up three containers (client, shadowbox, target) and two networks.
  • Creates a user on shadowbox.
  • Connects to target through shadowbox using a Shadowsocks client: client <-> shadowbox <-> target
  1. Testing Changes to the Server Config:

If your change includes new fields in the server config which are needed at server start-up time, then you mey need to remove the pre-existing test config:

  • Delete Existing Config: rm /tmp/outline/persisted-state/shadowbox_server_config.json

  • Manually Edit: You'll need to edit the JSON string within src/shadowbox/Taskfile.yml.