---
title: "Security groups"
description: "Segment your project"
url: "https://metalhost.net/docs/dashboard/guides/security-groups"
---

# Security groups

Security groups control **east-west** traffic — how your VMs talk to each other over the project's private network. By default every VM talks freely; attach a security group to a VM and it's locked down to that group's rules. Think of a group as a reusable firewall you stamp onto any set of VMs.

## How it works

- **Project-scoped** — security groups live in a project and apply to that project's VPC. Manage them under *Networking → Security groups*.
- **Allow-all by default** — a VM with no security group attached accepts all private traffic from other project VMs.
- **Default-deny once attached** — the moment a VM has at least one group, its private NIC drops everything except what the group's rules explicitly allow.
- **Stateful** — allow an inbound flow and its replies come back automatically; you don't write a matching reverse rule.
- **Additive** — attach several groups to a VM and it allows the union of all their rules.
- **Private NIC only** — security groups never touch the public NIC. Inbound from the internet is the [firewall](https://metalhost.net/docs/dashboard/guides/firewall.md).

> **groups vs. the firewall**
>
> **Security groups** = traffic *between your VMs* (private network). **Firewall** = traffic from the *internet* to a VM's public IP. Different surfaces, different tabs — a rule in one never affects the other.

## Rules

Each rule allows traffic in one direction:

- **Direction** — *ingress* (traffic arriving at the group's members) or *egress* (traffic leaving them).
- **Protocol** — TCP, UDP, or ICMP.
- **Port / range** — a single port or an inclusive range (TCP/UDP only; ICMP has no ports).
- **Source / destination** — either a **CIDR** (e.g. `10.0.0.0/8`, or an IPv6 range) or **another security group**. Referencing a group means "any VM that's a member of that group," and the rule follows membership automatically as VMs come and go.

## Example: a database tier

Say you want your database VMs reachable on `5432` only from your application VMs, and nothing else:

1. Create a group `app` (no rules needed) and attach it to your application VMs.
2. Create a group `db` with one ingress rule: **TCP 5432 from group `app`**.
3. Attach `db` to your database VMs.

Now the database VMs accept Postgres only from app VMs — every other private flow to them is dropped. Add or remove app VMs later and the rule keeps working; you never edit a CIDR list.

## Create a group

**Networking → Security groups → New security group**. Give it a name, add rules with the rule builder (direction, protocol, port/range, and a CIDR or group reference for the peer), and save. A group with no rules is valid — it locks its members down to nothing inbound until you add rules, or you can use it purely as a *reference* target for other groups' rules.

## Attach & detach VMs

Membership is mutable — you don't have to decide at create time:

- **At create** — pick groups in the VM create form's networking section.
- **Anytime after** — VM detail → *Security groups* panel → *Attach group*, or detach with the × on a chip.
- From the group's own card, you can see and remove its current members.

> **attaching the first group changes behavior**
>
> A VM with no groups talks freely. Attaching its first group flips it to default-deny on the private NIC — if that group doesn't include the flows the VM actually needs (e.g. to your database or cache), those connections start failing. Add the rules first, then attach.

## What's next

- [VPC & private network](https://metalhost.net/docs/dashboard/guides/networks.md) — the network security groups apply to.
- [Firewall rules](https://metalhost.net/docs/dashboard/guides/firewall.md) — the internet-facing counterpart.
- [Go SDK — Network](https://metalhost.net/docs/developers/guides/sdk-network.md).
