# The edge
URL: https://synquic.tech/docs/guides/the-edge.md

Synq's built-in reverse proxy. How your apps get a public address and HTTPS, how you protect a route, where your traffic numbers come from, and how to take over a proxy that's already running on a server.

import { Step, Steps } from 'fumadocs-ui/components/steps';

Every request from the internet has to land *somewhere* first, before Synq knows which of your apps it's for.
That somewhere is the **edge**: a reverse proxy (OpenResty) that sits on ports `80` and `443` and acts as the
front door for the whole server. It answers the connection, handles HTTPS, works out which app the hostname
belongs to, forwards the request to that app's container, and counts it on the way past.

Most of the time you never think about it: installing Synq sets the edge up for you, and every deploy that has a
domain wires that domain into it automatically. You start caring about the edge directly in a few moments: when
you move an existing server across, when you route a bare hostname at a port, when you rate-limit or block
something, or when you ask "where is my traffic actually coming from?"

<Callout title="The edge vs. the server" type="info">
Two different things run on a box, and it's worth keeping them straight. The **server** is Synq itself: the API
and dashboard, the control room. The **edge** is the public reverse proxy in front of your apps: the front door.
They're installed together; a visitor's request only ever touches the edge, never the server.
</Callout>

## What the edge actually does

Four jobs, all on the request path:

- **HTTPS for free.** It ends TLS with a Let's Encrypt certificate for each domain and redirects plain HTTP to
  HTTPS once the certificate is in place. See [HTTPS and certificates](/docs/guides/https-certificates).
- **Routing.** It maps each hostname to the right container. That's how ten apps share one server and one IP,
  each on its own domain.
- **Protection.** Route rules (redirects, basic auth, rate limits, IP, country and user-agent bans, allow-lists)
  are enforced here, before a request reaches your app. See
  [Redirects, basic auth and security rules](/docs/guides/edge-rules).
- **Traffic counting.** Because it already sees every request, it tallies them (requests, bandwidth, status
  codes, latency, countries, paths) at essentially no cost. That fills the analytics on the
  [Monitoring page](/docs/dashboard/monitoring) and each project's Monitoring tab.

It also serves a few pages of its own: "not deployed yet" for a ready domain whose project isn't live, "Application
unavailable" when an app doesn't answer, and "Service not found" for an unknown hostname (see
[What visitors see](/docs/guides/https-certificates#what-visitors-see-before-an-app-is-live)).

<Callout title="What you need first">
- A Linux server: the edge is a Linux reverse proxy. On macOS or Windows you can still *read* an edge's domains
  and traffic from the CLI, but installing and taking over the proxy happens on the Linux box.
- Synq installed on that box (with the installer, see [Installation](/docs/getting-started/installation)).
  The edge comes with it.
- For anything that reads data on a CLI-installed instance, a login: run `synq login` once with a token from the
  dashboard.
</Callout>

## Taking over a server that's already serving

This is the headline case. You have a server that's *already* running nginx, Apache or Caddy on `:80/:443` with
real sites on it, and you want Synq to run the front door instead, without a moment where nothing is served.

The edge does this as a **migration**: it reads the existing proxy's sites, registers each one on the edge so it
keeps serving, and only then takes the ports. The whole thing is journaled and rolls back cleanly if a step
fails, so you never end up with neither proxy up.

<Steps>

<Step>

### See what's there

On the server, ask the edge what it would import:

```bash
synq edge sites
```

It lists the reverse-proxy sites it found on the host: the hostnames and where each currently points.

</Step>

<Step>

### Take over and bring the sites across

```bash
synq edge migrate
```

That imports every site it just listed, then frees `:80/:443` and starts serving them from the edge. If you'd
rather *not* keep the old sites and just want the ports, use `synq edge takeover` instead, which stops the old
proxy without importing anything.

</Step>

</Steps>

<Callout title="You don't have to go looking for this" type="info">
When a foreign proxy is holding `:80/:443`, Synq raises the same "there's another proxy here, take over and
migrate its sites?" prompt **automatically** during `synq up` and in the bare `synq` control panel. The commands
above are the manual version of that offer, for when you want to run it on demand.
</Callout>

## Putting a domain on the edge

Once the edge is running, giving an app a public hostname is one command. You can point a domain at an existing
project, or bind a fresh one straight to a local port:

```bash
# Point a host at a port on this box (creates a tracked project for it)
synq edge domains add app.example.com --port 8080

# Attach a host to an existing project (uses that project's port)
synq edge domains add www.example.com --project prj_123 --primary
```

Registering a domain also verifies it and issues the HTTPS certificate. If DNS isn't pointing at the box yet,
the command prints the record to add and you re-run verification once it has propagated. The full domain
workflow (DNS records, verification, primary and redirects) lives in the
[Custom domains](/docs/guides/custom-domains) guide; in the panel, the [Domains page](/docs/dashboard/domains)
lists every domain the edge serves.

## Protecting a route

Rules are applied by the edge itself, so an abusive request is turned away before it costs your app anything.
Scope a rule to a whole project, one domain, or a path prefix, and combine as many conditions as you like:

```bash
# 20 requests/second per client IP on the login path, allowing short bursts
synq edge rules add -p prj_123 --path /login --rate-limit 20 --burst 40

# Block two countries and a bad IP, answering with 403
synq edge rules add -p prj_123 --ban-country RU,CN --ban-ip 203.0.113.7 --block-status 403

# Only let an office network in; deny everyone else
synq edge rules add -p prj_123 --allow-cidr 198.51.100.0/24

synq edge rules list -p prj_123
```

In the panel, the project's **Redirects** and **Security** entries edit the same rules, including basic auth and
path redirects. See [Redirects, basic auth and security rules](/docs/guides/edge-rules).

<Callout title="Rules that key on IP need the real client IP" type="warn">
Rate limits, IP bans and country rules only work if the edge sees the visitor's true address. Directly exposed,
it does. Behind Cloudflare's proxy it does too: the edge trusts Cloudflare's published ranges and reads
`CF-Connecting-IP`. Behind any other proxy, load balancer or tunnel, every visitor looks like the proxy.
`SYNQ_EDGE_TRUSTED_PROXIES` and `SYNQ_EDGE_REAL_IP_HEADER` fix that only for an edge installed directly on a
server, not for the edge container of a standard (Docker Compose) install. See
[Real visitor IPs](/docs/guides/cloudflare-tunnel#real-visitor-ips).
</Callout>

## Custom directives

For the rare case the built-in settings don't cover, an organization admin can add raw OpenResty directives to
one domain. Synq checks them, runs `openresty -t` and rolls back automatically if the edge refuses them. See
[Custom proxy config](/docs/guides/custom-proxy-config).

## Watching your traffic

Because the edge counts every request as it passes, you get a traffic picture with no code and no cost to your
visitors. There are three ways to see it.

**In the dashboard**, the [Monitoring page](/docs/dashboard/monitoring) shows every server and app together:
health dials, live requests per second, error rate, latency percentiles, a per-app table and a world map. A
project's **Monitoring** tab shows the same for one app (see [App monitoring](/docs/guides/app-monitoring)), and
**Logs → Server** has the individual request lines (see [Logs & monitoring](/docs/guides/logs-monitoring)).

**Per server**, the server's **Overview** tab adds its traffic panel and resource history (see
[Server monitoring and alerts](/docs/guides/server-monitoring)).

**From the terminal**, the same numbers are three commands:

```bash
# Requests, bandwidth, and hourly periods
synq edge traffic -p prj_123

# Visitors, countries, and top paths for one domain
synq edge analytics -p prj_123 --domain app.example.com

# The recent raw request log, and follow it live
synq edge logs -p prj_123 --follow
```

<Callout title="Where the numbers come from" type="info">
**The edge counts; the control plane collects.** The proxy bumps counters in shared memory as each response goes
out: no database, no extra network hop, nothing a visitor waits on. The **Traffic analytics collection** job moves
the minute totals into the database every 30 minutes, and opening a chart fetches the newest minutes first. Live
numbers (requests in flight, the last 60 seconds) are read straight from the edge. A fresh app shows nothing
until it's had some traffic.
</Callout>

## Prefer the full command reference?

Everything here is a task-level walkthrough. For the complete list of `synq edge` subcommands and every flag
(the interactive panel, `up`/`repair`, all the domain, rule and analytics options) see the
[Edge & monitoring](/docs/cli/edge) CLI reference.

## Related guides

<Cards>
  <Card title="Edge & monitoring (CLI)" href="/docs/cli/edge" description="Every synq edge subcommand and flag, in full." />
  <Card title="Custom domains" href="/docs/guides/custom-domains" description="DNS records, verification, and certificates end to end." />
  <Card title="Monitoring page" href="/docs/dashboard/monitoring" description="Servers, traffic and apps on one screen." />
  <Card title="Migrate from other platforms" href="/docs/guides/migrate-from-coolify-dokploy-dokku" description="Bring an existing box across, edge and all." />
</Cards>
