Setup Cloudflare CDN protected Trojan-Go with Docker on Ubuntu 20.04

Before we start

Setup Trojan-Go server

Create Docker-Compose configuration file

Create docker-compose.yml which contains the official Trojan-Go image, and a NGINX web server.

mkdir -p ~/trojan-go/
nano ~/trojan-go/docker-compose.yml
version: '3.5'
    container_name: trojan-server
    image: p4gefau1t/trojan-go
      - type: bind
        source: ./config/trojan/config.json
        target: /etc/trojan/config.json
      - type: bind
        source: ./config/trojan/cert.pem
        target: /etc/trojan/cert.pem
      - type: bind
        source: ./config/trojan/private.key
        target: /etc/trojan/private.key
      - 443:443
    command: ["trojan-go", "-config", "/etc/trojan/config.json"]
    restart: unless-stopped
    container_name: trojan-nginx
    image: nginx:alpine
      - type: bind
        source: ./config/nginx/nginx.conf
        target: /etc/nginx/conf.d/default.conf
    restart: unless-stopped

Press CTRL+X, Y, ENTER to save and exit nano text editor.

Create NGINX configuration file.

mkdir -p ~/trojan-go/config/nginx/
nano ~/trojan-go/config/nginx/nginx.conf
server {
    listen      80 default_server;
    server_name _;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;

server {
    listen 8080	http2;
    server_name	_;
    return	400;

Create Trojan-Go configuration file.

mkdir -p ~/trojan-go/config/trojan/
nano ~/trojan-go/config/trojan/config.json
  "run_type": "server",
  "local_addr": "",
  "local_port": 443,
  "remote_addr": "trojan-nginx",
  "remote_port": 80,
  "log_level": 2,
  "log_file": "",
  "password": [
  "disable_http_check": false,
  "udp_timeout": 60,
  "ssl": {
    "verify": true,
    "verify_hostname": true,
    "cert": "/etc/trojan/cert.pem",
    "key": "/etc/trojan/private.key",
    "key_password": "",
    "cipher": "",
    "curves": "",
    "prefer_server_cipher": false,
    "sni": "",
    "alpn": [
    "session_ticket": true,
    "reuse_session": true,
    "plain_http_response": "",
    "fallback_addr": "",
    "fallback_port": 0,
    "fingerprint": "firefox"
  "tcp": {
    "no_delay": true,
    "keep_alive": true,
    "prefer_ipv4": true
  "mux": {
    "enabled": true,
    "concurrency": 64,
    "idle_timeout": 60
  "router": {
    "enabled": false,
    "bypass": [],
    "proxy": [],
    "block": [],
    "default_policy": "proxy",
    "domain_strategy": "as_is",
    "geoip": "$PROGRAM_DIR$/geoip.dat",
    "geosite": "$PROGRAM_DIR$/geosite.dat"
  "websocket": {
    "enabled": true,
    "path": "/websocket",
    "host": ""
  "shadowsocks": {
    "enabled": false,
    "method": "AES-128-GCM",
    "password": ""
  "transport_plugin": {
    "enabled": false,
    "type": "",
    "command": "",
    "plugin_option": "",
    "arg": [],
    "env": []
  "forward_proxy": {
    "enabled": false,
    "proxy_addr": "",
    "proxy_port": 0,
    "username": "",
    "password": ""
  "mysql": {
    "enabled": false,
    "server_addr": "localhost",
    "server_port": 3306,
    "database": "",
    "username": "",
    "password": "",
    "check_rate": 60
  "api": {
    "enabled": false,
    "api_addr": "",
    "api_port": 0,
    "ssl": {
      "enabled": false,
      "key": "",
      "cert": "",
      "verify_client": false,
      "client_cert": []

The content above contains all available options. You may modify them when needed. The necessary changes are as follow:


"password": [


"sni": "",

Websocket path and host-name, so CDN could work

"websocket": {
    "enabled": true,
    "path": "/websocket",
    "host": ""

You may find out the explaination of other options in the official documentation. It is in simplified Chinese.

Obtain keys from Cloudflare

Go to Cloudflare. Navigate to the SSL/TLS page of the domain-name.

Choose Full. Full (strict) does not work as it is not supported by Trojan-Go yet.

Switch to Origin Server tab.

Keep Authenticated Origin Pulls to be Off, since we don't use Full (strict) mode.

Click the Create Certificate button.

Just keep everything unchanged. Click Next

nano ~/trojan-go/config/trojan/cert.pem

Copy the content of Origin Certificate to the file cert.pem.

nano ~/trojan-go/config/trojan/private.key

Copy the content of Private key to the file private.key.

Point the domain-name to your server

Navigate to DNS page.

Click + Add record to add two records.

  • Type A, name @, content SERVER-IP-ADDRESS
  • Type CNAME, name www, content YOUR-DOMAIN-NAME

Both records should be Proxied so everyone will see Cloudflare CDN IP address instead of the server's, to increase security.

Start Trojan-Go

cd ~/trojan-go/
docker-compose up -d

Test Trojan-Go

To check log file of both servers

cd ~/trojan-go/
docker-compose logs -f

Visiting your domain-name in a web-browser, you will see the NGINX welcome page.

When someone track your network activity, they would see you visiting this website frequently. So you should decorate this website to make it real.

To use Trojan-Go as a proxy visiting the blocked websites, connect Trojan-Go server using Trojan-Go client with the correct password.

Subscribe to theMatrixDev

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
[email protected]