Skip to content

Overview

dcvix is a three-component session broker and server-pool manager for Amazon DCV remote desktops. This page explains the system architecture, component relationships, and key lifecycle flows.

Three-Tier Model

flowchart LR
    L[Launcher] -- HTTPS / PASETO --> D[Director]
    D -- mTLS / CA-signed certs --> A1[Agent]
    D -- mTLS / CA-signed certs --> A2[Agent]
    A1 -- DCV sessions --> W1[Workstation]
    A2 -- DCV sessions --> W2[Workstation]
    subgraph Users
        L
    end
    subgraph Central
        D
    end
    subgraph Workstations
        A1
        A2
    end
Component Role Tech
Director Central server - API, auth, session management, CA authority Go + React frontend
Agent Per-workstation - DCV session lifecycle, stats reporting, auto-cert management Go
Launcher End-user GUI - login, server list, launch DCV viewer Go + Fyne toolkit

Session connection flow

flowchart TB
    User["User"]

    subgraph Client["Client Machine"]
        direction TB
        Launcher["dcvix Launcher"]
        Viewer["DCV Viewer"]
    end

    subgraph Control["dcvix Control Plane"]
        Director["dcvix Director"]
    end

    subgraph DCVHost["DCV Host"]
        direction TB
        Agent["dcvix Agent"]
        DCV["DCV Server<br/>(User Session)"]
    end

    User --> Launcher

    Launcher <-->|"1-3. Authenticate,<br/>list hosts, select +<br/>request session"| Director
    Director -->|"4. Create session"| Agent
    Agent -->|"5. Create"| DCV
    DCV -->|"6. Ready"| Agent
    Agent -->|"7. Session info"| Director
    Director -->|"8. Token + endpoint"| Launcher
    Launcher -->|"9. Launch with token"| Viewer
    Viewer -->|"10. Connect + present token"| DCV
    DCV <-->|"11-12. Validate token"| Director
    DCV -->|"13. Desktop session"| Viewer

The dcvix Launcher is the entry point for users. When a user requests a desktop session, the Launcher authenticates with the dcvix Director, which is responsible for authorization and session allocation.

The Director returns the list of available workstations and pools to the Launcher. The user selects the desired workstation. Then the Launcher asks the Director to create the session. The Director instructs the dcvix Agent running on the selected host to create a new DCV session. Once the session is ready, the Director generates a connection token and returns the required connection information to the Launcher.

The Launcher starts the DCV Viewer and passes the connection token to it. The DCV Viewer then connects directly to the DCV Server hosting the session.

During the connection process, the DCV Server validates the token by contacting the dcvix Director. The Director confirms whether the token is valid and authorized, allowing or rejecting the connection.

This architecture keeps the desktop traffic between the user and the DCV Server, while dcvix only manages authentication, authorization, and session lifecycle operations.

User Authentication Flow

sequenceDiagram
    participant User
    participant Launcher
    participant Director
    participant AuthBackend as Auth Backend (PAM/LDAP/...)

    User->>Launcher: Enter credentials (+ optional OTP)
    Launcher->>Director: POST /v1/user/login
    Director->>AuthBackend: Authenticate (PAM/LDAP/RADIUS/external)
    AuthBackend-->>Director: success
    Director->>Director: Generate PASETO v4 token (2h expiry)
    Director-->>Launcher: 200 OK + PASETO token
    Launcher->>Launcher: Store token
    Launcher->>Director: GET /v1/user/servers (session cookie)
    Director->>Director: Verify token, look up policy (users.json)
    Director-->>Launcher: 200 OK (server list)
    Launcher->>User: Display available servers

Session Lifecycle

sequenceDiagram
    participant User
    participant Launcher
    participant Director
    participant Agent
    participant DCV as DCV Server

    User->>Launcher: Select server + session type
    Launcher->>Director: Forward request (authenticated)
    Director->>Agent: POST /v1/sessions (mTLS)
    Agent->>DCV: dcv create-session <params>
    DCV-->>Agent: Session created
    Agent-->>Director: 200 OK (session info)
    Director-->>Launcher: 200 OK (session token)
    Launcher->>User: Launch dcvviewer

    Note over Agent: Periodic updates
    Agent->>Director: POST /v1/agent/update (sessions + stats)
    Note over Director: Updates in-memory session state

    User->>Launcher: Close session
    Launcher->>Director: DELETE /v1/sessions/{id}
    Director->>Agent: DELETE /v1/sessions/{id} (mTLS)
    Agent->>DCV: dcv close-session <id>
    DCV-->>Agent: Session closed
    Agent-->>Director: 200 OK
    Director-->>Launcher: 200 OK

Agent Auto-Registration Flow

On first startup, an agent has no certificate. It generates a key pair and GUID locally, then registers with the director via a retry loop. The private key never leaves the agent.

sequenceDiagram
    participant Agent
    participant Director
    participant Admin

    Note over Agent: First startup
    Agent->>Agent: Generate Ed25519 key pair
    Agent->>Agent: Generate UUIDv4 GUID (persisted)
    Agent->>Director: POST /v1/agent/register (CSR + GUID + hostname)
    Note over Agent,Director: Plain HTTPS (TOFU or pre-deployed CA)
    Director->>Director: Verify CSR CN matches GUID
    Director->>Director: Create pending entry in agents.db
    Director-->>Agent: 403 "pending approval"
    Note over Agent: Retry every 30 seconds

    loop Every 30s
        Agent->>Director: POST /v1/agent/register (same GUID + new CSR)
        Director-->>Agent: 403 "pending approval"
    end

    Admin->>Director: Approve agent via web UI
    Note over Director: Sign CSR -> 14-day cert
    Director-->>Agent: 200 OK (signed cert + CA cert)
    Agent->>Agent: Store agent.crt + ca.pem
    Note over Agent: Switch to strict mTLS
    Agent->>Agent: Start mTLS server + renewal loop

Flow details:

  • Key generation: Ed25519, stored at {dataDir}/agent.key (0600)
  • GUID: UUIDv4, stored at {dataDir}/agent.guid, survives restarts
  • CSR: CN = dcvix-agent-{guid}, DER-encoded, base64 in JSON
  • Director validation: Parses CSR, verifies CN matches submitted GUID (binds GUID to public key)
  • Agent states: pending -> registered -> revoked

Certificate Renewal Flow

Once registered, the agent renews its certificate periodically (default every 12 hours). The renewal uses the existing mTLS connection.

sequenceDiagram
    participant Agent
    participant Director

    Note over Agent: Every ~12 hours
    Agent->>Agent: Check CertificateNeedsRenewal() (<24h to expiry)
    Agent->>Agent: Generate new CSR (same key pair)
    Agent->>Director: POST /v1/agent/renew (CSR)
    Note over Agent,Director: mTLS (current cert)
    Director->>Director: Verify mTLS cert CN = GUID
    Director->>Director: Verify agent state = registered
    Director->>Director: Verify CSR CN matches mTLS GUID
    Director->>Director: Sign new CSR -> 14-day cert
    Director-->>Agent: 200 OK (signed cert)
    Agent->>Agent: Store new agent.crt

The mTLS server uses a GetCertificate callback so the renewed cert is picked up without restarting the listener.