Self-hosted outbound firewall
Restrict the outbound traffic of a self-hosted server's app host to the documented destinations, roll the rule out in alert mode first, and test it.
The app host of a self-hosted server can reach any destination by default. Your network team blocks outbound traffic at the network layer. This page tells them what to allow, how to build the rule, and how to test it.
The destination list is in Self-hosted infrastructure. This page does not copy it. Use that table as the source of truth.
What to allow
- Allow each row the table marks Required for your deployment.
- Allow an optional row only when you set its knob.
- Allow
models.dev, or setCH_COST_PRICING_SYNC=0. The price sync is on by default. A blocked sync logs a failure and keeps the old prices. - Add each webhook receiver host that you configure.
The server makes no AI inference calls. Devices call Anthropic, Bedrock or your gateway. Devices are out of scope for this page.
Build the rule
A security group cannot match host names. Use one control for each kind of destination.
- AWS services. Create VPC interface endpoints for KMS, SES, Cognito, ECR and STS. Create a gateway endpoint for S3. Allow egress only to the endpoint security group and the S3 prefix list.
- PostgreSQL. Allow port 5432 (or your DSN port) to the database security group only.
- Internet hosts. These are git hosts, Slack, webhook receivers, your OTLP collector,
models.devandapi.anthropic.com. Use a domain allowlist in AWS Network Firewall. It matches the TLS server name. - DNS. Allow port 53 to the VPC resolver.
- Instance metadata.
169.254.169.254is link-local. It never crosses the firewall, so it needs no rule.
Use Network Firewall, not an egress proxy. Some server HTTP clients do not read HTTPS_PROXY. The webhook client builds its own transport with no proxy setting. A proxy rule would miss that traffic.
Roll it out
- Set the firewall rule to alert only. Use a Network Firewall alert rule, or VPC Flow Logs.
- Run for one week. Compare the hosts you observe with the inventory table.
- Add each missing host that a real feature needs. Remove any host you do not want.
- Switch to deny by default.
- Alarm on dropped flows from the app host.
Test the rule
Run these tests from the app host.
-
Probe each allowed host. Each command must connect:
for h in api.github.com slack.com models.dev; do curl --silent --output /dev/null --connect-timeout 5 "https://$h" && echo "ok $h" || echo "BLOCKED $h" doneAdd your own hosts to the list. Use only hosts you allowed.
-
Run a negative control.
curl --connect-timeout 5 https://example.commust fail. If it connects, the rule is open. -
Test the product after you enforce the rule. Check
/v1/health, sign in, upload an attachment, send an invite mail, and run a price sync withPOST /v1/instance/cost-pricing/sync. Then run the checks in Self-hosted synthetic checks. -
Repeat after every upgrade. Compare the inventory table with the one from the previous release.
Related guides
- Self-hosted infrastructure — the outbound destination table and the AWS permissions
- Self-hosted synthetic checks — prove sign-in, mail and secrets still work
- Mail, spend and security detections — alarms for spend and mail
- Self-hosting CodeHerder — set up and run your own server
Last updated