DEV Community

Lia
Lia

Posted on

How to Reverse Proxy Multiple Sites with One WAF Instance

A single SafeLine instance can reverse proxy several sites when you install it once and add each site as its own application. The add-application guide describes SafeLine as a web application firewall developed based on nginx. It accepts HTTP or HTTPS traffic for the original site, filters malicious requests, and forwards the remaining traffic to the upstream address you configure (https://docs.waf.chaitin.com/en/GetStarted/AddApplication). Those getting-started pages do not document a multi-site wizard, a bulk import, path-based routing, or an upstream load-balancing policy. Treat this as a decision checklist plus one tested application entry per site. Do not point every domain at the instance until each entry has been checked.

Decide before you move DNS

Use one instance only when every hostname can resolve to that SafeLine server and the server can reach every origin. SafeLine is a self-hosted WAF. The product overview says a reverse proxy placed in front of a web app filters and monitors HTTP traffic and can block attacks such as SQL injection, XSS, code injection, OS command injection, CRLF injection, LDAP injection, XPath injection, RCE, XXE, SSRF, path traversal, backdoor, brute force, HTTP flood, and bot abuse (https://docs.waf.chaitin.com/en/home). The same page lists IP-based rate limiting, a web access control list, bot defense, HTML and JavaScript encryption, CAPTCHA challenge, and authentication challenge. Those controls apply to applications you have added. They do not create a path to an origin the host cannot reach.

If one site uses a private address that SafeLine cannot open, leave that site off this instance. Fix reachability first. Saving a domain in the console does not open a tunnel, and the supplied pages do not describe service discovery.

Check the host

Follow the deploy guide before installation (https://docs.waf.chaitin.com/en/GetStarted/Deploy). It requires Linux, x86_64 or arm64, Docker 20.10.14 or above, Docker Compose 2.0.0 or above, and a minimum of 1 CPU core, 1 GB memory, and 5 GB disk. The CPU must support ssse3.

  1. Run uname -m and continue only for x86_64 or arm64.
  2. Run docker version and confirm Docker is 20.10.14 or newer.
  3. Run docker compose version and confirm Compose is 2.0.0 or newer.
  4. Run cat /proc/cpuinfo | grep "processor", free -h, and df -h to review CPU, memory, and disk.
  5. Run lscpu | grep ssse3. Stop if ssse3 is missing.

The deploy guide also states that SafeLine installed on ARM requires a Pro license to work properly, and that the Personal Edition is not supported on ARM. If this host is ARM and you do not have that license, choose another host.

Install one instance

Automatic installation is the recommended path and requires root. The deploy guide gives this command:

bash -c "$(curl -fsSLk https://waf.chaitin.com/release/latest/manager.sh)" -- --en

After it completes, open the console at https://<safeline-ip>:9443/.

Use the manual path when you need to see each file. The same guide orders the work as follows.

  1. Install Docker if it is not already present, using the Docker install command published in the deploy guide. Skip that step when Docker is already installed.
  2. Create the data directory with mkdir -p "/data/safeline". SafeLine writes configuration and data here, so keep at least 5 GB free.
  3. Change to that directory and download the compose file with wget "https://waf.chaitin.com/release/latest/compose.yaml".
  4. Create .env and set SAFELINE_DIR, IMAGE_TAG, MGT_PORT, POSTGRES_PASSWORD, SUBNET_PREFIX, IMAGE_PREFIX, ARCH_SUFFIX, RELEASE, REGION, and MGT_PROXY. The sample in the guide uses MGT_PORT=9443 and MGT_PROXY=0.
  5. Generate DETECTOR_MGMT_TOKEN and MGT_INTERNAL_TOKEN as 64-character hex strings, and DETECTOR_AES_KEY as 16 alphanumeric characters, with the random commands in the deploy guide. Write those values into .env, then run chmod 600 .env.
  6. On an ARM server, set ARCH_SUFFIX=-arm and use the ARM Postgres image named in the guide. For the LTS channel, set RELEASE=-lts. The guide says the LTS version will no longer be maintained starting from 9.1.0-LTS (14 August 2025), and it recommends the current release unless you have a reason to stay on LTS.
  7. Create the documented resources directories, apply the documented permissions, and link the socket with ln -sfn /data/safeline/resources/run/safeline.sock /var/run/safeline.sock.
  8. Start the services with docker compose up -d. The guide says this may take several minutes.
  9. Run docker exec safeline-mgt resetadmin, save the printed username and password, and log in at https://<safeline-ip>:9443/.

MGT_PORT is the console port. MGT_PROXY counts console proxy layers and should remain 0 unless you are configuring a proxy for the console. Do not use the console port as the public port for your sites.

Add each site

In the web console, open Applications and click Add Application. Enter the three fields defined in the add-application guide.

  1. Domain: the domain, hostname, or IP of the original app.
  2. Port: the port SafeLine will listen on, such as 80 or 443. For an HTTPS app, check the SSL option.
  3. Upstream: the real address SafeLine will use when it forwards cleaned traffic.

Save that application, then repeat the same dialog for the next site. Keep a table of domain, listen port, SSL choice, and upstream, and compare it with what the console stored. The supplied guide does not ask for a weight, a health check, or a path rule. If a site needs those, this documented flow does not provide them, so do not assume they are active.

After you save a site, resolve that domain to the IP address of the SafeLine server. Clients should connect to SafeLine. SafeLine should connect to the upstream. Move domains one at a time:

  1. Add only the next application.
  2. Resolve only that domain to the SafeLine IP.
  3. Load the site through the public hostname and confirm the origin response.
  4. Send one documented test request to that same hostname.
  5. Continue to the next domain only after this one both loads and can be blocked.

The add-application guide includes test cases for SQL injection, XSS, path traversal, code injection, and XXE. Use your own domain in place of the sample host. A block page means that request was denied. Open the attack list in the console and click detail to inspect it. Test every domain. A block on the first site does not prove that the second application was entered correctly.

Cut over only after this checklist

  1. The host still meets the architecture, Docker, Compose, CPU, memory, and disk minimums in the deploy guide.
  2. Each Domain value matches the hostname clients will request.
  3. Each listen port is the port clients will use, and SSL is checked only for HTTPS applications.
  4. Each Upstream is the origin address, and the SafeLine host can reach it.
  5. DNS for that hostname points at the SafeLine server.
  6. A normal request returns the site, and one documented attack probe returns the block page.
  7. The console remains on its own port and is not published as one of the sites.

Turn on rate limiting, CAPTCHA challenge, authentication challenge, or dynamic protection only after forwarding works. The overview says an authentication challenge requires a password, and dynamic protection encrypts HTML and JavaScript on each visit. Those controls can affect legitimate users, so enable them per site after the proxy test, not while you change DNS for every domain at once.

Can one installation front several domains?

Yes, if you add a separate application for each domain, hostname, or IP. The getting-started pages show one Add Application dialog, not a bulk importer. Enter and test each site before you move the next DNS record.

Do the sites have to share one listen port?

No. Port is the port SafeLine will listen on for that application. The guide gives 80 and 443 as examples. Use the port clients will open, and check SSL when the application is HTTPS. Leave the console port, 9443 in the sample .env, separate from site traffic.

Where should each domain resolve?

Resolve it to the IP of the server where SafeLine is installed. That is the instruction in the add-application guide. Put the origin address only in Upstream.

How do I confirm filtering, not just proxying?

Send one of the documented attack probes to that domain and expect the block page. Then open the console attack list and click detail. Repeat the check for every application you added.

What should stay off this instance?

Keep off any site that needs a routing feature the add-application dialog does not collect, such as a load-balancing policy or a path-based split, and any origin the SafeLine host cannot already reach. The supplied install and application pages do not document a tunnel or automatic site discovery.


SafeLine has surpassed 700,000 installations worldwide as of September 30, 2026. SafeLine Pro annual promotional pricing is $650-$880, compared with the regular $1,000 per year.

Top comments (0)