# Private Networking

> Run private internal services with \*-tcp processes and let trusted apps reach them — no DNS, no certificates, no VPC plumbing.

Not every service should be on the public internet. Watasu lets one app expose private TCP services and another app reach them — without DNS, certificates, or VPC plumbing.

## Private TCP processes

Any process whose name ends in `-tcp` is a private TCP service:

```text
web:      bundle exec puma
grpc-tcp: bundle exec grpc_server
```

`grpc-tcp` is reachable from inside your team's runtime, but **not from the public internet**. There's no public DNS name and no TLS certificate — it's a raw TCP endpoint exposed to other apps that you explicitly trust.

The process listens on `$PORT` like any other, and trusted apps reach it at the internal hostname `<app>-<process>` — for the example above, `my-app-grpc-tcp`.

Common uses:

* internal gRPC service consumed by a public API
* private job intake for a worker fleet
* admin-only RPC between control and data planes
* microservice-to-microservice calls within a team

## Granting trust

The app that **exposes** a `*-tcp` service decides who can reach it. It keeps a trust list of sibling apps; only the apps on that list can connect.

To let `api-app` (and `billing-app`) reach the `*-tcp` services of `grpc-app`:

```bash
watasu apps:trust api-app,billing-app --app grpc-app
```

Run it without arguments to see the current list, or with `--clear` to revoke everyone:

```bash
watasu apps:trust --app grpc-app
watasu apps:trust --clear --app grpc-app
```

Trust is **directional** — being on `grpc-app`'s list lets you call `grpc-app`; it gives `grpc-app` no access in return.

## Picking the right process suffix

Use this rule:

| What you're doing                   | Process name                                                                  |
| ----------------------------------- | ----------------------------------------------------------------------------- |
| Public HTTP/WebSocket traffic       | `web` or `*-web`                                                              |
| Internal service-to-service traffic | `*-tcp` (with explicit trust)                                                 |
| WebRTC / UDP / real-time            | `*-rtc` (see [Real-Time and WebRTC](https://docs.watasu.io/apps/realtime.md)) |
| Background work nothing calls into  | any other name (typically `worker`)                                           |

The temptation to "just expose it on the public web with a hard-to-guess path" is real, but it's a worse default. `*-tcp` is the same effort, narrower blast radius, and easier to reason about when an audit happens.

## Microservices without the platform tax

Watasu's process model gives you most of what microservice deployments need without a service mesh:

* **Service discovery** — apps in the same team find each other by app name
* **Network isolation** — `*-tcp` is private by default; trust opens the door explicitly
* **Independent scaling** — each app scales its own pods, sizes, and replica counts
* **Independent deploys** — each app has its own Git push, release, and rollback timeline

For most teams that's enough. If you outgrow it, your container images are still standard containers — nothing here locks you into Watasu.

## The default network policy

Watasu doesn't run an open network. Every team gets its own isolated namespace with a default-deny posture:

| Direction                           | Default | Allowed by default                           |
| ----------------------------------- | ------- | -------------------------------------------- |
| Inbound from other teams            | Denied  | Nothing                                      |
| Inbound from same team              | Denied  | Only between apps with explicit trust grants |
| Outbound to the public internet     | Allowed | DNS, HTTPS, and standard outbound traffic    |
| Outbound to public Watasu hostnames | Allowed | Re-enters via the platform's public ingress  |

This means:

* Your app can call external APIs (Stripe, OpenAI, etc.) without configuration.
* Two apps in your own team can't reach each other unless you explicitly grant trust.
* Two apps in different teams can never reach each other directly.

### Calling your own apps

If app A needs to call app B's `*-tcp` service: add A to B's trust list with `watasu apps:trust A --app B`.

If app A needs to call app B's **public** HTTPS URL (e.g. a webhook): just use the public hostname (`app-b.watasuhost.com` or your custom domain). The request leaves the cluster via the public egress, then re-enters via the platform's ingress — same as if it came from outside. No trust grant needed.

## What private networking doesn't do

It doesn't replace authentication. Trust controls reachability; your app still needs to authorize callers (e.g. mTLS, signed tokens, shared secrets) for anything sensitive.

[View this page on the web](https://docs.watasu.io/apps/private-networking/)
