# Fork and restore

> Copy a running machine at one instant, or restore one of a machine's snapshots, as a new machine with its own ID and identity.

**Fork** copies a running machine into a new machine at one instant. **Restore** creates a new machine from one of a machine's ready [snapshots](/docs/guides/snapshots). Neither changes the source machine.

> [!NOTE]
> Use `vy fork` and `vy restore`, the SDKs (`machine.fork`, `machine.restore`), the HTTP API below, or the console (**Fork** on a machine's overview or row menu, **Restore as new machine** on its Snapshots tab). Owners, Admins, and Operators fork and restore.

## Fork a running machine

```sh
curl -X POST "$VMYARD_API_URL/v1/machines/$MACHINE_ID/fork" \
  -H "Authorization: Bearer $VMYARD_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"live": true, "name": "dev-copy", "keep_ssh_keys": false}'
```

| Field | Meaning |
| --- | --- |
| `live` | Default `true`: the copy starts running. `false` creates it stopped. |
| `name` | Optional display name for the copy. |
| `keep_ssh_keys` | Default `false`. `true` keeps the login user's `authorized_keys` inside the guest. |

The source must be running (`409 machine_not_running`). A fork is **point-in-time**: VMYard pauses the source only while it writes memory and clones the disk, so the copy has every write that completed before the fork, including data still in the page cache. The fork runs in the source's operation queue, after every operation requested on the source before it, so "write a file, then fork" always copies the file.

## Restore a snapshot

```sh
curl -X POST "$VMYARD_API_URL/v1/machines/$MACHINE_ID/restore" \
  -H "Authorization: Bearer $VMYARD_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"snapshot_id": "'"$SNAPSHOT_ID"'", "name": "dev-restored", "wake": true}'
```

The snapshot must belong to that machine and be `ready` (`409 snapshot_not_ready`). `wake` (default `true`) starts the new machine; `false` creates it stopped. A warm snapshot resumes its processes; a cold one boots fresh from its disk. The source machine is untouched, so to replace it, delete it after the restore succeeds. `keep_ssh_keys` works as for a fork.

## What a copy is

Both answer `202` with an operation whose `machine_id` names the **new** machine. Follow that operation like a create: it ends with the new machine observed running, or observed stopped when you asked for `live: false` or `wake: false`. The new machine reports `forked_from_machine_id` or `restored_from_snapshot_id`.

- **New identity.** The copy has its own machine ID. Before it is reported running, the guest's machine ID, host name, SSH host keys, and kernel random state are reset, so copies never share them.
- **Same tenant alias.** The copy keeps its source's tenant alias (its machine name), because the runtime scopes snapshots and forks to that alias. Its display name is `name` if you sent one. Search finds both by the alias.
- **Same size and placement.** The exact plan, image, region, resources, and backend of the source; the default auto-stop.
- **No ports or SSH access.** A copy never inherits exposed ports or the SSH gateway key. [Expose ports](/docs/guides/ports) and [set an SSH key](/docs/guides/ssh) again; `keep_ssh_keys` only keeps the key inside the guest.
- **Environment.** A fork carries its source's environment and applied version. A restore carries the version that was applied when the snapshot was taken.
- **Billing.** A copy is admitted like a create (balance, trial machine class, plan price, concurrency, start windows). A copy created stopped holds no auto-stop deadline and is not metered until you start it.

Webhooks: a live fork or woken restore emits `machine.ready` when it is observed running; a copy created stopped emits `machine.stopped`.
