> For the complete documentation index, see [llms.txt](https://docs.defguard.net/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.defguard.net/2.2/in-depth/architecture-decision-records/2.3.md).

# 2.3

## Always-On Machine Tunnel

### The problem

* Multiple users share each device, so VPN access cannot depend on the account of the first person who enrolls it.
* Device sign-in depends on Active Directory or another service reachable only from the corporate network.
* Therefore the device needs a machine-level VPN connection established before any user logs in.
* The device fleet is too large for administrators to manually provision and maintain each machine.

### Requirements

{% hint style="warning" %}
**Assumption:** Initial enrollment will happen on the corporate network. Later users may enroll while the device is remote. They need VPN access before signing in, when no user session is available to establish a user-owned tunnel.
{% endhint %}

* After initial user enrollment (inside the corporate network), a device-level VPN must be available before Windows sign-in.
* The connection must continue across user changes and after the first enrolling user is removed, so other users can reach directory and authentication resources and enroll remotely.
* Each machine must have an independent identity visible to administrators, who can revoke access per VPN or remove the machine entirely.
* Configuration changes and revocation must synchronize centrally without requiring a user login.
* Existing enrollment and client behavior must be preserved where the machine-level capability is not required.

### Solution

* When creating an enrollment token, the administrator can choose to also create an always-on machine identity and select the service location it should connect to.
* During the first user enrollment on the corporate network, the device also receives its own VPN identity.
* A Windows service keeps the device tunnel connected before sign-in, independently of who is using the device.
* Later users can reach the corporate network to sign in and enroll, even when the device is outside the office.
* Administrators can see the shared device, manage its VPN access, and remove it without affecting users' personal devices.
* Changes to the device tunnel configuration are applied without requiring a user to sign in.

### Implementation plan summary

* Add a new `DeviceType::Shared` enum variant
* Allow null on `Device::user_id` for this new device type records
* Introduce a `shared_device_user` join table with `shared_device_id`, `user_id`, and `enrolled_at` fields to record which users enrolled on each shared device and when.
* Erollment `/start` endpoint returns additional flag that informs the client if shared device also has to be provisioned
* Introduce new enrollment endpoints for device and user enrollment with shared device provisioning to avoid additional complexity in the old enrollment endpoints
* New clients can react to the flag from the `/start` endpoint by using the new enrollment endpoints
* Old clients ignore the information and use the old endpoints - core can decide if such enrollment should be allowed (TBD)
* After the first enrollment, client passes shared device's config to the privileged Windows service, which stores it in ACL-protected directory, the same way reqular service-tunnels are stored.
* Administrators can manage and revoke access to individual VPNs or remove the machine entirely.

### Considered options

#### 1. Client enrolls the user, then provisions the machine device

The Desktop Client completes the user's enrollment, obtains or creates a machine-device enrollment result, and passes the machine configuration and polling credentials to the existing Windows background service. The service stores the configuration and brings up the tunnel.

**Pros**

* Reuses the existing Windows service, which already reads service-location configuration and manages WireGuard tunnels.
* Keeps the user enrollment UI flow responsible for user interaction.
* Avoids introducing another Windows service and its packaging/update lifecycle.

**Cons**

* The existing service does not poll Core. It would need to store the machine polling token, poll independently, and apply configuration changes while the machine tunnel is active.
* Requires changes to the enrollment/API flow and the IPC contract between the Desktop Client and service.
* The current flow creates the user's device before user activation completes. We need to decide when machine provisioning happens and what to do if activation succeeds but machine provisioning fails, or vice versa.

#### 2. Client passes a machine enrollment token to the existing service

The Client completes the user's enrollment and passes a machine-specific enrollment token to the service. The service generates or owns the machine key, redeems the token, saves the resulting configuration, and brings up the tunnel.

**Pros**

* The machine private key can remain under the service's control rather than passing through the user-session process.
* Reuses the existing service for configuration storage and tunnel management.
* Does not require the service to receive a fully assembled tunnel configuration from the UI.

**Cons**

* The current user enrollment token is single-use and cannot simply be redeemed once by the Client and again by the service. This requires a separate machine token/proof or a change to Core's token semantics.
* The Client still needs to hand the token to the service through a secure IPC path.
* Like option 1, the service would need its own polling implementation.
* The background service must generate and securely store the machine's WireGuard private key. Today, the UI generates the key pair and passes the private key to the service, so this adds key-generation and persistence to the service.

#### 3. Add a separate Windows service based on `dg`

A new Windows service would read a machine token/config file, enroll the Network Device, establish its tunnel, and poll Core for updates.

**Pros**

* The existing `dg` code already implements Network Device enrollment and polling.
* Separates the machine tunnel's lifecycle and credentials from the Desktop Client service.

**Cons**

* `dg` currently handles exactly one device configuration. Its polling path expects exactly one config, so supporting multiple service locations requires changes to `dg`, not just a file watcher.
* The current `dg` token flow configures a Network Device that already exists in Core and is attached to the token. It does not create a new machine device during a user's enrollment.
* `dg` is currently released and packaged for Linux. There is no supported or shipped `dg.exe` or Windows Network Device service. Windows MSI resources include `defguard-service.exe` and a different binary, `defguard-cli.exe`; the Windows release workflow is currently disabled.
* A new executable/service adds Windows installation, signing, upgrades, diagnostics, and interaction with the existing service. Both services must not fight over interface names, routes, or DNS.

### Decision

We choose option 1: the Desktop Client completes the user's enrollment, then provisions a separate machine identity and passes its configuration to the existing Windows background service. The service stores and maintains the machine's always-on tunnel independently of the user's session.

#### Rationale

This reuses the existing Windows service for tunnel storage and lifecycle, avoiding a second service and its separate installation and maintenance. A distinct machine identity keeps VPN access independent of the first enrolling user's account, while dedicated enrollment endpoints limit changes to existing enrollment flows.
