> ## Documentation Index
> Fetch the complete documentation index at: https://help.onetsolutions.net/llms.txt
> Use this file to discover all available pages before exploring further.

# VPC — Private Networking

> Create a private network so your instances can talk to each other without going through the internet

A VPC is a private network for your instances. Instances attached to the same VPC reach each other over private addresses, without their traffic leaving for the public internet.

The usual reason to want one: a database that should be reachable by your application server and by nothing else. Instead of exposing port 3306 publicly and defending it, you do not expose it at all.

<Info>
  **Prerequisites**

  * An OnetSolutions account with a project
  * At least one instance, or the intention to create some
</Info>

## Creating a VPC

<Steps>
  <Step title="Open VPC">
    In the console, go to **Compute** and open the **VPC** tab.
  </Step>

  <Step title="Start creating">
    Click **Create VPC**.
  </Step>

  <Step title="Name the network">
    Fill in **Network Name** — something describing its role, such as `prod-backend`.
  </Step>

  <Step title="Choose the CIDR block">
    Enter a private IP range in **CIDR Block**, for example `10.0.0.0/16`. This defines the addresses instances on this network receive.
  </Step>

  <Step title="Create">
    Confirm. The network appears in the list with its status.
  </Step>
</Steps>

<Warning>
  The CIDR block and the location cannot be changed after creation. Both are fixed for the life of the VPC — getting them wrong means deleting the network and starting again, which means detaching every instance on it first.
</Warning>

## Choosing a CIDR Block

Use a range reserved for private networks. Three blocks are set aside for this:

| Block            | Range                         | Addresses                                      |
| ---------------- | ----------------------------- | ---------------------------------------------- |
| `10.0.0.0/8`     | 10.0.0.0 – 10.255.255.255     | The most room; `10.0.0.0/16` is a common slice |
| `172.16.0.0/12`  | 172.16.0.0 – 172.31.255.255   | Often used by Docker — check for conflicts     |
| `192.168.0.0/16` | 192.168.0.0 – 192.168.255.255 | Familiar from home networks                    |

A `/16` gives you 65,536 addresses, which is generous for most projects and leaves room to grow. There is no benefit in being tight here.

<Note>
  Pick a range that does not collide with anything else you connect to — your office network, a VPN, or Docker's default bridge. Overlapping ranges cause routing problems that are tedious to diagnose after the fact, and the CIDR cannot be changed later.
</Note>

## Attaching an Instance

<Steps>
  <Step title="Open the instance">
    In **Compute**, open the instance you want to attach.
  </Step>

  <Step title="Go to its VPC tab">
    Select the **VPC** section for that instance.
  </Step>

  <Step title="Associate">
    Pick the network from **Available VPCs** and click **Associate**.
  </Step>
</Steps>

<Note>
  A VPC belongs to a location, and only instances in that same location can join it. If the list is empty, the instance is in a location where you have no VPC yet.
</Note>

To detach later, use **Dissociate** on the same screen. The instance immediately loses access to the other instances on that private network, so check nothing depends on it first.

## Using the Private Network

Once two instances share a VPC, they reach each other over their private addresses. Find the private address on the instance:

```bash theme={null}
# Private interfaces and their addresses
ip -4 addr show | grep -v "127.0.0.1"
```

Then bind services to the private address instead of every interface. For PostgreSQL:

```
# postgresql.conf — listen on the private address only
listen_addresses = '10.0.1.20'
```

For MySQL or MariaDB:

```ini theme={null}
# my.cnf
bind-address = 10.0.1.20
```

<Warning>
  Binding to a private address is what actually closes the service off. A database listening on `0.0.0.0` is reachable from the internet whether or not a VPC exists — the VPC adds a private path, it does not remove the public one.
</Warning>

Verify what is listening where:

```bash theme={null}
# Every listening socket, with the address it is bound to
ss -tlnp
```

Anything showing `0.0.0.0:` is exposed on the public interface.

## VPC and Firewall

The two solve different problems and work together. The VPC provides a private path between instances; the [firewall](/vps/firewall) controls what may travel over it and what may reach the instance publicly.

A private network is not by itself a permission system — every instance attached to the same VPC can reach every other one. If that is too broad, firewall rules are what narrow it.

## Troubleshooting

<AccordionGroup>
  <Accordion title="No VPC appears in the instance's list">
    The instance is in a different location from your VPC. A VPC only accepts instances in the location it was created in — create one in the instance's location.
  </Accordion>

  <Accordion title="Two instances are attached but cannot reach each other">
    Check the service is bound to the private address rather than to localhost, then check the firewall allows the traffic between them. `ss -tlnp` on the target answers the first question.
  </Accordion>

  <Accordion title="The private address is missing on the instance">
    A newly attached instance may need its network reconfigured or a reboot before the interface appears. Confirm with `ip -4 addr show`.
  </Accordion>

  <Accordion title="Routing behaves strangely after attaching">
    Usually an overlap between the VPC range and another network the instance uses, most often Docker's default bridge on `172.17.0.0/16`. Compare with `ip route`.
  </Accordion>
</AccordionGroup>

<Tip>
  The pattern worth adopting: application server with a public address, database on the VPC only. It removes an entire class of exposure, and it costs nothing beyond planning the addresses once.
</Tip>
