> For the complete documentation index, see [llms.txt](https://docs.ipcheck.ing/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.ipcheck.ing/developer/pt-br/getting-started/reverse-proxy-and-domains.md).

# Proxy Reverso e Domínios

Coloque o MyIP atrás de um proxy reverso, restrinja o acesso à API aos seus domínios e configure endpoints de IP amigáveis para o curl.

O MyIP serve HTTP puro na porta `18966` e não encerra TLS. Para qualquer implantação pública, coloque um proxy reverso na frente dele.

## Proxyando para o MyIP

Não há nada de incomum para configurar. Aponte seu proxy para a porta `18966` e pronto:

* **Não é necessário tratar upgrade de WebSocket.** O backend do MyIP usa HTTP puro.
* **Não `try_files` ou regras de rewrite para SPA.** O servidor frontend já faz fallback para `index.html` para rotas do cliente como `/tools/whois`.
* **Não `/api` sem tratamento especial.** O mesmo servidor faz proxy de `/api` para o backend internamente.
* **Não adicione cache no nível do proxy.** O MyIP define seus próprios `Cache-Control` por classe de recurso — recursos com hash são imutáveis por um ano, `index.html` é revalidado, `/api/*` usa por padrão `no-store`. Substituir isso fará com que páginas desatualizadas sejam servidas após um deploy.

{% tabs %}
{% tab title="Nginx" %}
{% code title="/etc/nginx/sites-available/myip" %}

```nginx
server {
    listen 443 ssl http2;
    server_name myip.example.com;

    ssl_certificate     /etc/letsencrypt/live/myip.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/myip.example.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:18966;
        proxy_http_version 1.1;

        proxy_set_header Host              $host;
        proxy_set_header X-Real-IP         $remote_addr;
        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
```

{% endcode %}
{% endtab %}

{% tab title="Caddy" %}
{% code title="Caddyfile" %}

```
myip.example.com {
    reverse_proxy 127.0.0.1:18966
}
```

{% endcode %}

O Caddy gerencia certificados TLS e define os `X-Forwarded-*` cabeçalhos para você.
{% endtab %}
{% endtabs %}

### Cabeçalhos importantes

O backend roda com o trust proxy do Express `trust proxy` definido para um salto e resolve o IP do cliente nesta ordem:

1. `CF-Connecting-IP` (Cloudflare)
2. a primeira entrada de `X-Forwarded-For`
3. `CF-Connecting-IPv6`
4. o endereço do socket

Esse endereço é o que a limitação de taxa e o registro de IP bloqueado anotam. Se o seu proxy não encaminhar `X-Forwarded-For`, todo visitante parece ser um único cliente e os limites de taxa se aplicam a todos eles juntos. Veja [Opções de Segurança](/developer/pt-br/configuration/security-options.md).

{% hint style="info" %}
**Tamanho do corpo da requisição.** Relatórios de diagnóstico compartilhados enviam até 500 KB para `/api/report`, e se você habilitar o túnel frontend do Sentry, `/api/monitoring` aceita envelopes de até 10 MB. Se você restringir `client_max_body_size` (o padrão do Nginx é 1 MB), mantenha-o acima desses limites.
{% endhint %}

## `ALLOWED_DOMAINS` — necessário em um domínio real

Toda `/api/*` rota está atrás de uma `Referer` verificação. A requisição é rejeitada com **403** a menos que o `Referer` hostname do cabeçalho seja `localhost` ou apareça em `ALLOWED_DOMAINS`.

Isso é o que impede outros sites de incorporar sua instância e usar suas chaves de API e seus limites de taxa. Esse também é o erro de self-hosting mais comum: o app carrega e depois toda ferramenta falha.

{% hint style="danger" %}
Se você servir o MyIP em `https://myip.example.com` e deixar `ALLOWED_DOMAINS` vazio, **toda a API retorna 403**. A página renderiza, e nada nela funciona.
{% endhint %}

```bash
ALLOWED_DOMAINS="myip.example.com,www.myip.example.com"
```

Comportamento exato, para você acertar de primeira:

| Regra                  | Detalhe                                                                                                         |
| ---------------------- | --------------------------------------------------------------------------------------------------------------- |
| Separador              | Vírgula. **Sem espaços** — as entradas são comparadas literalmente, e `" b.com"` nunca corresponde a nada.      |
| Correspondência        | Hostname exato. `example.com` não **não** permite `sub.example.com`, e vice-versa.                              |
| `www`                  | Um hostname separado. Liste ambos se ambos estiverem acessíveis.                                                |
| Porta e caminho        | Ignorado. `example.com` cobre `https://example.com:8443/anything`.                                              |
| `localhost`            | Sempre permitido, seja qual for a sua configuração.                                                             |
| Endereço IP bruto      | É tratado como um hostname. Para acessar o app em `http://192.168.1.10:18966`, adicione `192.168.1.10` à lista. |
| Ausente `Referer`      | Rejeitado com `{"error":"O que você está fazendo?"}`.                                                           |
| Hostname não permitido | Rejeitado com `{"error":"Acesso negado"}`.                                                                      |

{% hint style="info" %}
A ausência de `Referer` é sempre uma rejeição, e é por isso que `curl https://myip.example.com/api/...` retorna 403 por design. A API existe para o frontend da própria app, não para scripts diretos.
{% endhint %}

## Endpoints de IP amigáveis para curl

O MyIP tem um painel "Command Line API" que mostra aos visitantes um `curl` comando de uma linha para verificar o IP a partir de um terminal. O opcional `/geo` caminho adiciona geolocalização à resposta:

```bash
curl 4.example.com
curl 4.example.com/geo
```

Três variáveis controlam quais hostnames o painel exibe:

| Variável                 | Entrada do painel                                   |
| ------------------------ | --------------------------------------------------- |
| `VITE_CURL_IPV4_DOMAIN`  | Obter o endereço IPv4 da máquina                    |
| `VITE_CURL_IPV6_DOMAIN`  | Obter o endereço IPv6 da máquina                    |
| `VITE_CURL_IPV64_DOMAIN` | Obter o IP de saída de rede preferencial da máquina |

Aponte-os para hostnames que resolvam conforme isso — apenas A, apenas AAAA e dual-stack.

{% hint style="warning" %}
**Os três são obrigatórios.** O frontend só mostra o painel curl quando todos eles estão definidos; se algum estiver vazio, o recurso permanece oculto e a caixa de diálogo diz que ele está indisponível.
{% endhint %}

{% hint style="warning" %}
**Estas são variáveis de build.** Como toda `VITE_*` variável, elas são incorporadas ao bundle JavaScript pelo Vite. Passá-las para a imagem Docker pré-compilada em runtime não faz nada — defina-as em `.env` antes de `pnpm run build`, ou antes de `docker build` na sua própria imagem. Veja [Implantar com Node.js](/developer/pt-br/getting-started/deploy-with-nodejs.md).
{% endhint %}

{% hint style="info" %}
**O MyIP não implementa o `/geo` endpoint.** Essas variáveis apenas informam ao frontend quais hostnames exibir no painel curl. O serviço que responde a `4.example.com/geo` é algo que você executa separadamente. Deixe as variáveis vazias e o recurso simplesmente permanece desativado — veja [Recursos vinculados ao IPCheck.ing](/developer/pt-br/configuration/features-tied-to-ipcheck-ing.md).
{% endhint %}

## Solução de problemas

<details>

<summary>A página carrega, mas toda ferramenta mostra um erro</summary>

Quase sempre `ALLOWED_DOMAINS`. Abra a aba de rede do seu navegador e procure respostas 403 em `/api/*`. O corpo da resposta diz qual caso você encontrou:

* `{"error":"Acesso negado"}` — o hostname não está na lista. Adicione o hostname exato que você digita na barra de endereços.
* `{"error":"O que você está fazendo?"}` — nenhum `Referer` chegou ao backend. Verifique se o seu proxy ou uma extensão de privacidade não está removendo-o.

Reinicie o backend após alterar `ALLOWED_DOMAINS`.

</details>

<details>

<summary>Os limites de taxa disparam para todos de uma vez</summary>

Seu proxy não está encaminhando o IP real do cliente, então todo o tráfego se concentra em um único endereço. Adicione `X-Forwarded-For` (veja o exemplo do Nginx acima) e reinicie.

</details>

<details>

<summary>Conteúdo desatualizado após uma atualização</summary>

Verifique se há cache adicionado no proxy ou no CDN. O MyIP já define cabeçalhos apropriados `Cache-Control` ; se o seu proxy fizer cache de `index.html` por mais tempo, os visitantes continuam carregando uma build cujos arquivos de recursos já não existem.

</details>

## Próximos passos

* [Opções de Segurança](/developer/pt-br/configuration/security-options.md) — limitação de taxa, desaceleração, registro de IP bloqueado
* [Variáveis de Ambiente](/developer/pt-br/reference/environment-variables.md)
* [Endpoints da API](/developer/pt-br/reference/api-endpoints.md)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.ipcheck.ing/developer/pt-br/getting-started/reverse-proxy-and-domains.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
