Firewall configuration on a cloud server is a short problem with a bad reputation. The policy is one sentence — deny everything inbound, then open exactly the ports you intend to serve — and almost every real incident comes from breaking that sentence for convenience.
There are two firewalls, and you want both
The provider firewall — called security groups, cloud firewalls or network rules depending on the platform — runs outside the instance. It is the stronger of the two, because a compromised server cannot disable it, and it keeps unwanted traffic off the machine entirely.
The host firewall — nftables, ufw, firewalld — runs on the instance. It is the one that still protects you if a rule is changed in the console by mistake, and the one that can express application-specific logic.
Running both is not redundant. It means a single mistake in either place is not sufficient to expose a service.
The default policy
- Inbound: deny. Everything, then add exceptions.
- Outbound: allow, for most workloads. Restricting outbound traffic is a real control for sensitive environments and a source of mysterious breakage everywhere else — do it deliberately or not at all.
- Established connections: allow, otherwise responses to your own requests are dropped.
What belongs open
- 443, and 80 only to redirect to it or to answer certificate challenges.
- Your SSH port, restricted by source address. Your office, your home, your VPN, your bastion — not
0.0.0.0/0. - Whatever else you genuinely serve to the public, which for most application servers is nothing.
What should never be open to the internet
- Database ports. Postgres, MySQL, MongoDB, Redis, Elasticsearch. Internet-exposed databases are found by scanners in minutes and are one of the most common causes of data loss on cloud servers.
- Admin panels and dashboards — the orchestration UI, the metrics UI, the queue UI. Behind the firewall or behind authentication that you trust, never simply on a high port.
- Remote desktop. Same rule as SSH: restricted by source, always.
- Anything you enabled temporarily to debug something. Write the closing step down when you write the opening one.
Use the private network for internal traffic
Application to database, application to cache, application to internal API — all of it should travel over the provider’s private network, addressed by private IP, and be blocked entirely on the public interface. This is better for security, better for latency, and usually cheaper, because private traffic within a zone is normally not billed. See egress and bandwidth charges.
Verify from outside
A firewall you have not tested from another network is an assumption. After configuration, scan your own public address from somewhere else and confirm that exactly the intended ports answer. Do this again after any change to the provider rules, because console changes take effect immediately and silently.
Where to go next
Questions
Frequently asked
Do I need a host firewall if the provider firewall is on?
It is worth having both. The provider firewall protects the instance from the network; the host firewall means a mistaken console change does not immediately expose a service.
Should SSH be open to the whole internet?
No. Restrict it to the addresses you actually connect from, or reach it through a bastion host or VPN. Key-only authentication plus a source restriction is the standard safe pairing.
Can I expose a database if it has a strong password?
Strongly inadvisable. Exposed database ports are scanned continuously, and the failure mode is total data loss. Keep databases on the private network and reach them from application servers only.
