Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .icons/parsec.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
160 changes: 160 additions & 0 deletions registry/coder/modules/parsec/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
---
display_name: Parsec
description: Install Parsec for low-latency cloud gaming and remote desktop on Windows workspaces
icon: ../../../../.icons/parsec.svg
verified: false
tags: [windows, gaming, streaming, remote-desktop]
---

# Parsec

Enable [Parsec](https://parsec.app/) for low-latency cloud gaming and remote desktop access on Windows workspaces. Parsec provides high-performance streaming with support for 4K, 60fps, and low-latency input.

```tf
module "parsec" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/parsec/coder"
version = "1.0.0"
agent_id = coder_agent.main.id
}
```

## Features

- **Low-latency streaming**: Sub-16ms latency for responsive gaming and productivity
- **High quality video**: Up to 4K resolution at 60fps
- **GPU acceleration**: Hardware encoding for smooth performance
- **Multi-monitor support**: Virtual monitors for cloud workspaces
- **Teams support**: Enterprise deployment with team computer keys

## Requirements

- Windows workspace with GPU support (recommended)
- Parsec account (free tier available)
- Parsec client installed on your local machine

## Examples

### Basic Installation

Install Parsec with default settings:

```tf
module "parsec" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/parsec/coder"
version = "1.0.0"
agent_id = coder_agent.main.id
}
```

### With Custom Hostname

Set a custom hostname for easier identification:

```tf
module "parsec" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/parsec/coder"
version = "1.0.0"
agent_id = coder_agent.main.id
host_name = "my-gaming-workspace"
}
```

### Parsec Teams Deployment

For enterprise/team deployments with automated authentication:

```tf
module "parsec" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/parsec/coder"
version = "1.0.0"
agent_id = coder_agent.main.id
parsec_team_id = var.parsec_team_id
parsec_team_key = var.parsec_team_key
}
```

### AWS Windows Template

Complete example with AWS Windows instance:

```tf
module "parsec" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/parsec/coder"
version = "1.0.0"
agent_id = coder_agent.main.id
}

# Recommended: Use GPU instance types like g4dn.xlarge for best performance
```

### GCP Windows Template

Complete example with Google Cloud Windows instance:

```tf
module "parsec" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/parsec/coder"
version = "1.0.0"
agent_id = coder_agent.main.id
}

# Recommended: Use N1 with NVIDIA T4 GPU for best performance
```

## Connecting to Your Workspace

1. **Install Parsec client** on your local machine from [parsec.app/downloads](https://parsec.app/downloads)
2. **Log in** to your Parsec account (same account as the workspace or Teams account)
3. **Find your workspace** in the Parsec computer list
4. **Click Connect** to start streaming

## Configuration Options

| Variable | Description | Default |
| ----------------- | ------------------------------------------- | -------------------- |
| `agent_id` | The ID of a Coder agent | Required |
| `display_name` | Display name for the Parsec app | `"Parsec"` |
| `slug` | Slug for the Parsec app | `"parsec"` |
| `icon` | Icon path | `"/icon/parsec.svg"` |
| `order` | App order in UI | `null` |
| `group` | App group name | `null` |
| `parsec_team_id` | Parsec Team ID for enterprise deployments | `""` |
| `parsec_team_key` | Parsec Team Computer Key for authentication | `""` |
| `host_name` | Custom hostname for the Parsec host | Workspace name |
| `auto_start` | Start Parsec service automatically | `true` |

## GPU Recommendations

For the best cloud gaming experience, use instances with dedicated GPUs:

| Cloud Provider | Recommended Instance Types |
| -------------- | -------------------------- |
| AWS | g4dn.xlarge, g5.xlarge |
| GCP | n1-standard-4 + NVIDIA T4 |
| Azure | Standard_NV6 |

## Troubleshooting

### Parsec not starting

- Ensure the workspace has GPU drivers installed
- Check Windows Event Viewer for Parsec service errors
- Verify network allows UDP traffic on ports 8000-8200

### High latency

- Use an instance in a region close to you
- Ensure hardware encoding is enabled (requires GPU)
- Check network quality between client and workspace

### Computer not appearing in Parsec

- Wait 1-2 minutes after workspace starts
- Verify Parsec service is running: `Get-Service parsec`
- Check Parsec logs in `%APPDATA%\Parsec\logs`
153 changes: 153 additions & 0 deletions registry/coder/modules/parsec/install-parsec.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
# Parsec Installation Script for Coder Workspaces
# This script installs and configures Parsec for cloud gaming and remote desktop

$ErrorActionPreference = "Stop"

Write-Output "=== Installing Parsec for Coder Workspace ==="

# Configuration from Terraform variables
$ParsecTeamId = "${parsec_team_id}"
$ParsecTeamKey = "${parsec_team_key}"
$HostName = "${host_name}"
$AutoStart = [System.Convert]::ToBoolean("${auto_start}")

# Parsec download URL and paths
$ParsecMsiUrl = "https://builds.parsec.app/package/parsec-windows.msi"
$ParsecInstallDir = "$env:ProgramFiles\Parsec"
$TempDir = "$env:TEMP\parsec-install"
$ParsecMsiPath = "$TempDir\parsec-windows.msi"

# Create temp directory
if (-not (Test-Path $TempDir)) {
New-Item -ItemType Directory -Path $TempDir -Force | Out-Null
}

# Check if Parsec is already installed
$ParsecInstalled = Test-Path "$ParsecInstallDir\parsecd.exe"

if (-not $ParsecInstalled) {
Write-Output "Downloading Parsec..."

# Download Parsec MSI
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
try {
Invoke-WebRequest -Uri $ParsecMsiUrl -OutFile $ParsecMsiPath -UseBasicParsing
} catch {
Write-Error "Failed to download Parsec: $_"
exit 1
}

Write-Output "Installing Parsec..."

# Install Parsec silently
$InstallArgs = @(
"/i"
"`"$ParsecMsiPath`""
"/qn"
"/norestart"
"ALLUSERS=1"
)

$InstallProcess = Start-Process -FilePath "msiexec.exe" -ArgumentList $InstallArgs -Wait -PassThru

if ($InstallProcess.ExitCode -ne 0) {
Write-Error "Parsec installation failed with exit code: $($InstallProcess.ExitCode)"
exit 1
}

Write-Output "Parsec installed successfully."
} else {
Write-Output "Parsec is already installed."
}

# Configure Parsec for headless/team deployment if credentials provided
$ParsecConfigDir = "$env:APPDATA\Parsec"
$ParsecConfigFile = "$ParsecConfigDir\config.txt"

if (-not (Test-Path $ParsecConfigDir)) {
New-Item -ItemType Directory -Path $ParsecConfigDir -Force | Out-Null
}

# Build configuration
$ConfigLines = @()

# Set hostname if provided
if ($HostName -ne "") {
$ConfigLines += "host_name = $HostName"
Write-Output "Setting Parsec host name to: $HostName"
}

# Enable hosting
$ConfigLines += "host_virtual_monitors = 1"
$ConfigLines += "host_privacy_mode = 0"

# Write config if we have any settings
if ($ConfigLines.Count -gt 0) {
# Read existing config if present
$ExistingConfig = @()
if (Test-Path $ParsecConfigFile) {
$ExistingConfig = Get-Content $ParsecConfigFile
}

# Merge configs (new values override existing)
$ConfigHash = @{}
foreach ($line in $ExistingConfig) {
if ($line -match "^([^=]+)=(.*)$") {
$ConfigHash[$Matches[1].Trim()] = $Matches[2].Trim()
}
}
foreach ($line in $ConfigLines) {
if ($line -match "^([^=]+)=(.*)$") {
$ConfigHash[$Matches[1].Trim()] = $Matches[2].Trim()
}
}

# Write merged config
$FinalConfig = $ConfigHash.GetEnumerator() | ForEach-Object { "$($_.Key) = $($_.Value)" }
$FinalConfig | Out-File -FilePath $ParsecConfigFile -Encoding UTF8

Write-Output "Parsec configuration updated."
}

# Configure for Parsec Teams if credentials provided
if ($ParsecTeamId -ne "" -and $ParsecTeamKey -ne "") {
Write-Output "Configuring Parsec Teams authentication..."

# For Parsec Teams, we need to configure the team computer key
$TeamConfigFile = "$ParsecConfigDir\team_config.txt"
@"
team_id = $ParsecTeamId
team_computer_key = $ParsecTeamKey
"@ | Out-File -FilePath $TeamConfigFile -Encoding UTF8

Write-Output "Parsec Teams configuration saved."
}

# Start Parsec if auto_start is enabled
if ($AutoStart) {
Write-Output "Starting Parsec..."

$ParsecExe = "$ParsecInstallDir\parsecd.exe"

if (Test-Path $ParsecExe) {
# Start Parsec in the background
Start-Process -FilePath $ParsecExe -WindowStyle Hidden
Write-Output "Parsec started successfully."
} else {
Write-Warning "Parsec executable not found at: $ParsecExe"
}
}

# Cleanup
if (Test-Path $TempDir) {
Remove-Item -Path $TempDir -Recurse -Force -ErrorAction SilentlyContinue
}

Write-Output "=== Parsec installation complete ==="
Write-Output ""
Write-Output "To connect to this workspace:"
Write-Output "1. Install Parsec client on your local machine: https://parsec.app/downloads"
Write-Output "2. Log in to your Parsec account"
Write-Output "3. This computer will appear in your Parsec computer list"
Write-Output ""
Write-Output "For Teams deployment, ensure you have configured team_id and team_computer_key."
Loading