Skip to main content

Networking

Available

Deployed and supported. The fields and commands described here are stable within version v1alpha1.

The network of an App is closed by default: a service only accepts connections on its declared ports, coming from the other services of the same App (and from the Internet if it is exposed), and goes nowhere except to the services of your tenant. Two fields open doors: allowFrom (another App of your tenant gets in) and egress: [internet] (the service goes out).

Prerequisites​

Steps​

1. Open what needs to be open​

shop.yml
apiVersion: deploy.stackngo.io/v1alpha1
kind: App
metadata:
name: shop
spec:
services:
api:
image: registry.gitlab.com/acme/shop-api:1.4.2
ports: ["8080"]
ingress: { port: 8080 }
egress: [internet] # calls a payment provider
dependsOn: [db]
db:
image: postgres:17
user: "999"
ports: ["5432"]
allowFrom: [reporting] # the tenant's "reporting" App can read the database
volumes:
- { path: /var/lib/postgresql/data, size: 10Gi }

On the command line: sng app create … --egress-internet --allow-from reporting, sng app patch shop --service api --egress-internet=false.

2. Apply and test​

sng apply shop.yml
sng app logs shop --service api --since 5m

From api, db:5432 responds; so does https://api.paiement.example. From db, a request to the Internet is blocked.

Verification​

A small probe job tells what gets through:

netcheck.yml
apiVersion: deploy.stackngo.io/v1alpha1
kind: App
metadata:
name: netcheck
spec:
services:
closed:
kind: job
image: curlimages/curl:8.11.1
user: "100"
size: xxxs
command: ["sh", "-c", "for u in https://example.com http://169.254.169.254/; do if curl -s -m 5 -o /dev/null $u; then echo \"OK $u\"; else echo \"BLOCKED $u\"; fi; done"]
open:
kind: job
image: curlimages/curl:8.11.1
user: "100"
size: xxxs
egress: [internet]
command: ["sh", "-c", "for u in https://example.com http://169.254.169.254/; do if curl -s -m 5 -o /dev/null $u; then echo \"OK $u\"; else echo \"BLOCKED $u\"; fi; done"]
sng apply netcheck.yml
sng app logs netcheck
[netcheck-closed-3f9a1c2e-x7k2q] BLOCKED https://example.com
[netcheck-closed-3f9a1c2e-x7k2q] BLOCKED http://169.254.169.254/
[netcheck-open-8b1d7e40-p9s4m] OK https://example.com
[netcheck-open-8b1d7e40-p9s4m] BLOCKED http://169.254.169.254/

Who can reach what​

Inbound to a service​

FromToAllowed?
another service of the same Appa port declared in portsyes
another service of the same Appan undeclared portno
another App of your tenanta declared portyes if the App is in allowFrom
the Internet (over HTTPS)the ingress port onlyyes if ingress
another tenantanythingnever
anyonea service without portsno: it accepts nothing

The rules are in place before the service starts: there is no window during which a service would be open.

Outbound from a service​

ToAllowed?
the services of your tenant (all Apps)yes, but the target service must accept (see above)
the platform DNSyes
the Internetonly with egress: [internet]
private addresses (other tenants, private networks, 169.254.169.254)never, even with egress: [internet]

egress only accepts the value internet; there is no opening by address or by port.

Naming services between each other​

A service db of the App shop that declares ports: ["5432"] is reachable by the other services of the App at db:5432, exactly as in compose. With the form "5433:5432", it is db:5433 that is exposed, to port 5432 of the container.

From another App of the tenant (allowed by allowFrom), use the same name: db:5432. Avoid giving the same service name to two Apps of a tenant: the second is rejected (NameConflict), because a service name is unique across the whole tenant.

allowFrom​

  • List of App names of your tenant (10 at most), not services.
  • Opens all ports of the service to the services of these Apps. No per-port granularity.
  • Requires at least one declared port, otherwise the manifest is invalid (allowFrom : le service n'a aucun port à ouvrir).
  • sng app patch shop --service db --allow-from '' removes all authorizations.

dependsOn and networking​

dependsOn orders the creation of services; it opens no door. A service can depend on another without being able to reach it (if the latter has no ports), and vice versa. For api to wait for db and talk to it: dependsOn: [db] on api, ports: ["5432"] on db.

If it doesn't work​

What you seeCauseFix
connection refused or timeout to db:5432The port is not in the ports of db, or the caller is in another App missing from allowFromDeclare the port, or add the App to allowFrom
A call to an external API times outThe service does not have egress: [internet]Add it, then sng apply
NameConflict on a serviceAnother App of the tenant has a service with the same nameRename one of the two services
Manifest rejected: allowFrom : le service n'a aucun port à ouvrirallowFrom on a service without portsDeclare at least one port

Going further​

  • These rules apply to every service and cannot be disabled.
  • Your containers receive no variable describing the other services: pass the addresses through env (DB_HOST: db).
  • Resolution of public names is always allowed: no additional opening is needed to resolve a name before reaching it with egress: [internet].

See also​