Setting up SDE VDI desktop pools

By Paul Flanders · · Intermediate

Learn how to set up on-demand desktop pools for Windows and Linux using SDE VDI with Proxmox, Active Directory, and Guacamole. This guide is for engineers deploying SDE VDI and covers everything from preparation to day-to-day operations.

Add on-demand desktop pools ("Windows 11 Desktop", "Linux Desktop") to an SDE Remote deployment: Proxmox, Active Directory, Guacamole, the sde-vdi unit, the gateway and the app, end to end.

Applies to: SDE Remote gateway 1.0.12+, SDE Remote app 1.1.2+, sde-vdi 0.5.9+, Proxmox VE 8/9 (single node or cluster) · Audience: engineers deploying SDE VDI for a site · Time: about half a day, plus building the gold template

1. What you're setting up

SDE VDI keeps a pool of desktops ready on Proxmox, cloned from a gold template. A user clicks the pool's tile in SDE Remote and gets a free desktop. When they sign out of Windows, that desktop is deleted and a fresh one is cloned. It's an optional add-on to an existing SDE Remote deployment, in its own GL unit.

PartRoleChanges needed
sde-vdi unit (new)Clones, prepares and recycles desktops. Hands them out. Admin page.Deploy it (section 7)
ProxmoxRuns the desktopsAn API token scoped to its own pools (section 3)
Active DirectoryDesktops join it; users sign in with itA desktops OU and a join account (section 4)
GuacamoleShows each pool as a connection; decides who may use itNone on a stock install, apart from the LDAP check (section 5)
sde-gateway (broker + rdpgw)Asks sde-vdi for a desktop and tunnels RDP to itVersion 1.0.12 or later and two environment lines (section 9)
sde-nginxServes the admin page at /sde-vdi/One location block (section 8)
SDE Remote appPool tiles, the "Preparing…" wait, the Admin → Desktop pools menu entryVersion 1.1.2 or later (section 12)

How a desktop is prepared. sde-vdi makes a linked clone and boots it. It waits for Windows setup to finish, then renames the desktop and restarts it. Next it sets DNS (if configured) and the classic Netlogon secure channel, joins the domain under the final name and restarts again. It then checks the domain trust, grants Remote Desktop to the pool's groups, makes sure the desktop's name resolves to its own address, and finally waits for RDP. Then the desktop is spare. Expect 5–8 minutes per desktop on the LAN and longer on an SDE Network, which is why the pool keeps spares ready.

Four scripts do most of the setup (in the repo's scripts/vdi and deploy/glitch-units folders):

ScriptRun itIt does
pve-bootstrap-sde-vdi.shOnce, as root on any Proxmox nodePools, role, user, token and permissions (section 3)
ad-bootstrap-sde-vdi.ps1Once, on a domain controllerOU, delegated join account, group, Group Policy, time check (section 4)
template-prep.ps1 / .sh + pve-template.shPer gold templatePrepares the master and releases template versions (section 6)
deploy-sde-vdi.sh --wireOnce, on the gateway hostInstalls the unit, writes both units' settings, adds the nginx route, tests (sections 7–9)

Each script prints the settings the next one needs, and each has a --check (-Check) mode that changes nothing. Afterwards, the admin page's Readiness tab checks everything live.

How a user connects. The app asks the gateway. The gateway checks in Guacamole that the user may use the pool, asks sde-vdi for a desktop, and issues a short-lived gateway token for it. FreeRDP connects through the gateway with the user's own credentials. While FreeRDP runs, the app checks in every minute.

Network paths to allow
  • Gateway host → Proxmox API: 8006.
  • Gateway host (sde-vdi and rdpgw) → desktops: 3389.
  • Gateway host (sde-vdi) → domain controllers: LDAPS 636 and DNS.
  • Desktops → domain controllers: DNS, Kerberos, LDAP, SMB, time.
  • Admins' browsers → portal: 443.
sde-vdi's own port (8096) only needs to be reachable from the gateway and nginx; never publish it outside. Set SDE_VDI_V1_NETWORKS so the gateway API answers only the gateway (section 14.1).

2. Before you start

You needNotes
A working SDE Remote deploymentGuacamole + sde-gateway + sde-nginx, as in the main install guide. Gateway image 1.0.12 or later (sde-remote-gateway:latest).
Proxmox VE 8 or 9Root access to one node's Shell for the one-off setup. Note which storage will hold the template: linked clones need LVM-thin, ZFS, Ceph or qcow2.
Windows licensingFor live, Windows 11 Enterprise with KMS or AD-Based Activation, and Microsoft 365 Apps with Shared Computer Activation if you install Office. For dev, an evaluation ISO is fine.
Active Directory adminTo create an OU and a join account, and optionally GPOs.
Guacamole adminTo grant the pool entries to users or groups.
Values to collectProxmox node URL(s), the DC name and IP, the AD domain (FQDN and NetBIOS), the desktops OU path, and gua_srv's password.

3. Proxmox: account and permissions

sde-vdi uses an API token that can only touch its own desktops and clone your templates. It's never root. Copy the repo's scripts/vdi folder to any node and run, once, as root (on a cluster it applies to every node):

bash pve-bootstrap-sde-vdi.sh                      # add --template <vmid> for existing templates
bash pve-bootstrap-sde-vdi.sh --check              # later: shows OK / FIX for each item, changes nothing

It detects Proxmox 8 or 9 for the guest-agent privileges, grants every storage that can hold disks (or only --storage X), and ends by printing the SDE_VDI_PVE_* lines for section 7, including the token secret, which is shown only once. --rotate-token replaces the token and prints a new secret.

3.1 What it does, as commands (to do it by hand)

pveum pool add sde-vdi  --comment "SDE VDI desktops (managed by sde-vdi)"
pveum pool add sde-gold --comment "SDE VDI gold templates"

# Proxmox 9:
pveum role add SDEVDI --privs "VM.Allocate VM.Clone VM.Audit VM.PowerMgmt VM.Config.Options VM.Config.Network VM.Config.Disk VM.Config.CDROM VM.Config.Cloudinit VM.GuestAgent.Audit VM.GuestAgent.Unrestricted"
# Proxmox 8: the same, but with VM.Monitor instead of the two VM.GuestAgent.* privileges.

pveum user add sde-vdi@pve --comment "SDE VDI service account"
pveum user token add sde-vdi@pve vdi --privsep 0      # copy the secret it prints (shown once)

pveum acl modify /               --users sde-vdi@pve --roles PVEAuditor
pveum acl modify /pool/sde-vdi   --users sde-vdi@pve --roles SDEVDI
pveum acl modify /pool/sde-gold  --users sde-vdi@pve --roles PVETemplateUser
pveum acl modify /sdn/zones/localnetwork --users sde-vdi@pve --roles PVESDNUser
# With SDE Network, sde-network grants the same role on /sdn/zones/sde (or use the script's --zone sde)
pveum acl modify /storage/<template-storage> --users sde-vdi@pve --roles PVEDatastoreUser   # e.g. /storage/datastore01

Put each gold template in the sde-gold pool (pveum pool modify sde-gold --vms <template-vmid>), or allow the token to clone it directly:

pveum acl modify /vms/<template-vmid> --users sde-vdi@pve --roles PVETemplateUser
Check itThe admin page's Readiness tab tests the token's privileges on the desktops pool, each pool's template and storage, and the network zone, and gives the exact command for anything missing.
Placement on a cluster
  • Shared storage (Ceph, NFS): clones can run on any node.
  • Local storage: clones run on the template's node. Tick only that node in the pool's settings, or keep an identical template, with the same name, on each node.

Skip this section only for workgroup desktops, where users sign in with local accounts on the desktop. That's suitable for dev, not live.

On a domain controller (or a machine with the AD and Group Policy tools), in an elevated PowerShell, run once:

powershell -ExecutionPolicy Bypass -File ad-bootstrap-sde-vdi.ps1            # -WhatIf to preview
powershell -ExecutionPolicy Bypass -File ad-bootstrap-sde-vdi.ps1 -Check     # later: OK / FIX only

It creates OU=sde with OU=desktops under it, the join account sde-vdi-join (random password, never expires, not a Domain Admin) with only the delegated rights below, the group sde-vdi-users, and a GPO with the session time limits. It also checks the PDC's time source. It prints the SDE_VDI_AD_* lines for section 7; the password is shown only once (-ResetPassword sets a new one). Options: -ParentOU, -OUName, -JoinAccount, -RdpGroup, -DisconnectedMinutes, -IdleMinutes, -NoGpo.

The subsections explain what it sets up, for doing it by hand or checking it.

4.1 OU for the desktops

Create an OU, for example OU=desktops,OU=sde,DC=corp,DC=local. sde-vdi joins every desktop there under its pool name (W11-OFF-001…). Names are reused, so the computer objects are reused too.

4.2 Join account

Create a user, for example sde-vdi-join. Set Password never expires, and don't make it a Domain Admin. Delegate it the rights to create, delete and join computers in the desktops OU only. In an elevated prompt on a DC, swapping in your OU and account:

$ou  = "OU=desktops,OU=sde,DC=corp,DC=local"
$who = "CORP\sde-vdi-join"
dsacls $ou /I:T /G "${who}:CCDC;computer"
dsacls $ou /I:S /G "${who}:CA;Reset Password;computer" "${who}:RPWP;Account Restrictions;computer" `
                   "${who}:WS;Validated write to DNS host name;computer" "${who}:WS;Validated write to service principal name;computer"

The same account reuses the computer objects it created, so Windows' rule against reusing someone else's computer account doesn't apply.

Deleting computer objects is part of the delegation because AD clean-up (section 14) uses this account too.

4.3 Group Policy on the desktops OU (recommended for live)

  • Session time limits. Under Computer Configuration → Administrative Templates → Windows Components → Remote Desktop Services → Remote Desktop Session Host → Session Time Limits: disconnected sessions 30 min; "End session when time limits are reached" Enabled. sde-vdi recycles a desktop once its user is signed out, so this is what clears abandoned sessions.
  • Remote Desktop rights. Use Restricted Groups / Group Policy Preferences to add your users' group to Remote Desktop Users. Or let sde-vdi do it per pool ("Allow Remote Desktop for", section 10).
  • Profiles. Desktops are wiped at sign-out. Use FSLogix or folder redirection plus home and project shares for anything users need to keep.

4.4 DNS and time

  • DNS: desktops must resolve the domain. If DHCP hands out a DNS server that can't (for example a router), set the pool's "DNS servers for the domain" to the DCs. The gateway host must also resolve <desktop>.<domain>, because the pool connects by name.
  • Time: the PDC emulator must have correct time, from external NTP. A DC clock that's hours out makes newly joined desktops lose their domain trust. On Proxmox, register a Windows DC VM with a Windows OS type, so its hardware clock is local time:
    w32tm /config /manualpeerlist:"pool.ntp.org,0x8" /syncfromflags:manual /reliable:yes /update
    w32tm /resync /force
  • Netlogon secure channel: sde-vdi sets UseKerberosForSecureChannels=0 on each desktop when it joins, so Windows uses the classic Netlogon channel. Without it, Windows 11 desktops on an SDE Network can't take domain sign-ins from a Windows Server 2025 DC. Nothing to set up; SDE_VDI_NETLOGON_KERBEROS=true turns it off.
  • Service accounts: the gateway's LDAP bind account and Guacamole's search-bind account must never expire. An expired one breaks sign-in in confusing ways.

5. Guacamole

Nothing is installed into Guacamole. sde-vdi uses its standard API, with the same service account the gateway uses (gua_srv, a Guacamole administrator). Check two things:

  • The LDAP user base covers your SDE users. In guacamole.properties (and the unit's environment, if the image builds its config from it), ldap-user-base-dn must contain every SDE user, for example OU=sde,DC=corp,DC=local. Users moved outside it can no longer sign in. Set ldap-group-base-dn to the whole domain so groups are found wherever they live.
  • Guacamole-only accounts, such as guacadmin, sign in to the app because the gateway skips its AD pre-check for them (SDE_LOCAL_ACCOUNTS, default guacadmin). Add any other break-glass accounts there. These accounts can't sign in to a domain desktop, so they're refused pool desktops unless the pool has Users sign in on the desktop ticked.

When the first pool is saved, sde-vdi creates the connection group "Desktop Pools (open in SDE Remote)" and a connection per pool in it.

6. Gold template

Build it with the template guides:

The scripts in the repo's scripts/vdi folder automate most of that: template-prep.ps1 / template-prep.sh run inside the master, and pve-template.sh (push, release, check) runs on the Proxmox node. The release step also grants the token clone rights.

Otherwise put it in the sde-gold pool or grant the token clone rights on it (section 3.1), and check it on the admin page's Templates tab. Guest agent, network and no-ISO should all pass, plus cloud-init for Linux.

7. Deploy the sde-vdi unit

On the gateway host, from a checkout of the sde-remote repo, one interactive run does sections 7, 8 and 9:

sudo deploy/glitch-units/deploy-sde-vdi.sh --wire --dry-run    # shows what it would change
sudo deploy/glitch-units/deploy-sde-vdi.sh --wire
  1. Installs the unit if it isn't there.
  2. Asks you to paste the lines printed by the two bootstrap scripts (an empty line ends the paste), then asks for anything missing. The Guacamole URL and gua_srv password default to the gateway's. It can fetch and install Proxmox's CA, so the certificate is checked.
  3. Generates the shared secret.
  4. Writes the sde-vdi settings and the gateway's two lines, showing the change with secrets masked and keeping a timestamped backup of each file.
  5. Adds the /sde-vdi/ route to sde-nginx and tests the config (it restores the backup if the test fails).
  6. Asks before restarting sde-vdi, the gateway and nginx.
  7. Tests: sde-vdi answers, the gateway reaches it with the right secret, the admin page loads through the portal, and /sde-vdi/v1/ is refused through the portal.

Run deploy-sde-vdi.sh --check any time to repeat only the tests. The rest of this section, and sections 8 and 9, describe the same changes for doing them by hand.

By hand:

sudo deploy/glitch-units/deploy-sde-vdi.sh       # pulls sde-vdi:latest and installs the unit

The first run installs /var/glitch-units/sde-vdi/glitch/config/enviroment and stops, asking for the secrets. Edit it:

SettingValue
SDE_VDI_PVE_URLProxmox API, e.g. https://pve01.corp.local:8006. On a cluster, list several, comma-separated.
SDE_VDI_PVE_TOKEN_ID / _SECRETsde-vdi@pve!vdi and the secret from section 3
SDE_VDI_PVE_INSECURE or _CA_FILEProxmox's own certificate: trust its CA file (/etc/pve/pve-root-ca.pem), or INSECURE=true on dev
SDE_VDI_GUAC_URLSame as the gateway's SDE_GUAC_URL
SDE_VDI_GUAC_ADMIN_USER / _PASSgua_srv and its password
SDE_VDI_SHARED_SECRETopenssl rand -hex 32. The gateway gets the same value (section 9).
SDE_VDI_AD_DOMAIN / _USER / _PASSThe AD domain (FQDN), the join account and its password. Leave unset for workgroup desktops.
SDE_VDI_AD_OUThe desktops OU. The pool editor suggests it for new pools.
SDE_VDI_AD_LDAP_*Optional. sde-vdi reads AD over LDAPS as the join account (Readiness, pool defaults, clean-up). It finds a DC through DNS and trusts the CA the DC presents; set _HOST, _SERVERNAME or _CA_FILE only if that fails.
SDE_VDI_V1_NETWORKSRecommended. Addresses allowed to call the gateway API, e.g. 172.16.0.0/12 (docker networks). See 14.1.
SDE_VDI_ADMIN_NETWORKSOptional. Who may open the admin page (default: private ranges).
SDE_VDI_PAUSEDtrue for the first start (read-only). Remove it afterwards.
SDE_VDI_MEM_CHECK / _NODE_MEM_RESERVE_MIBFree-memory guard per node (default on, 2 GiB headroom). false only on tight dev kit.

Every setting, with its default, is in the settings reference.

sudo chmod 600 /var/glitch-units/sde-vdi/glitch/config/enviroment
sudo deploy/glitch-units/deploy-sde-vdi.sh       # starts it
docker logs sde-vdi 2>&1 | head                  # expect: "Proxmox OK", "PAUSED", "listening on :8096"

Pool definitions and leases live in /var/glitch-units/sde-vdi/data/state. Keep it, and back it up with the host. sde-vdi also keeps a daily copy of its state in data/state/backups (the last 14 days). When the paused start looks right, comment out SDE_VDI_PAUSED and restart: gl -d sde-vdi && gl -s sde-vdi (or php /var/glitch-cli/gl.php …).

8. Admin page on the portal (nginx)

Add this to the portal's server { listen 443 … } block, next to /sde-broker/. A ready-made copy is in deploy/nginx/sde-vdi.conf. Add an upstream sde_vdi { server <host>:8096; } line if your config uses upstreams.

location = /sde-vdi { return 301 /sde-vdi/; }
location ^~ /sde-vdi/v1/ { return 404; }          # the gateway<->sde-vdi API is never exposed
location /sde-vdi/ {
    proxy_pass         http://<host>:8096/;       # trailing slash strips the prefix
    proxy_set_header   Host $host;
    proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header   X-Forwarded-Proto $scheme;
    proxy_read_timeout 60s;
}
docker exec sde-nginx nginx -t && docker exec sde-nginx nginx -s reload    # reload doesn't drop connections

Open https://<portal>/sde-vdi/ and sign in as a Guacamole administrator. It only opens from inside the network.

9. Switch pools on in the gateway

Add two lines to /var/glitch-units/sde-gateway/glitch/config/enviroment, then restart the gateway. The restart takes about 10 seconds and drops every native RDP session going through the gateway, pool desktops included. Users reconnect from SDE Remote; a pool user gets the same desktop and session back. Do it at a quiet time.

SDE_VDI_URL=http://<host>:8096
SDE_VDI_SECRET=<the same value as SDE_VDI_SHARED_SECRET>
gl -d sde-gateway && gl -s sde-gateway
docker logs sde-gateway 2>&1 | grep "desktop pools"     # expect: "desktop pools: sde-vdi 0.5.x … (api v1)"
Check itOpen the admin page's Readiness tab. Every line should be OK, or Check with a reason you accept. Each problem comes with its fix.

10. Create the first pool

On the admin page, go to Pools → New pool. Start with spare 1, maximum 2, and raise them once it's proven.

FieldWindows + ADLinux
Display nameWhat users see, e.g. Windows 11 DesktopLinux Desktop
Desktop OSWindowsLinux. This sets RDP to TLS and ticks "Users sign in on the desktop"
Gold templatePick from the list; the checks show underneathSame
Desktop namesW11-OFF-{nnn} (15 characters max)lnx-dsk-{nnn}
Spare desktops / Maximum desktopsSpares are ready and waiting. The maximum caps spare + in use + being prepared.Same
NetworkExisting LAN (the template's network card), or a private network from SDE NetworkSame
Grant to Guacamole groupsWho gets the pool, e.g. sde-vdi-users (section 11)Same
Spare desktops by time of dayOptional rules, e.g. 6 spare Mon–Fri 07:50–09:30 for the morning rush. The highest matching rule wins; otherwise the spare count.Same
Advanced → NodesThe template's node, on local storageSame
Advanced → Join domain: OUThe desktops OU (section 4.1)Leave empty
Advanced → DNS servers for the domainThe DCs' IPs, if DHCP's DNS can't resolve the domainEmpty
Advanced → DNS suffixThe AD domain, e.g. corp.local (connect by name)Empty (connect by IP)
Advanced → Allow Remote Desktop fore.g. CORP\Domain Users or CORP\sde-vdi-users, unless a GPO does itEmpty
Advanced → RDP security / domainNLA, domain = NetBIOS name (e.g. CORP)TLS
Advanced → Remote Desktop → Users sign in on the desktop (dev / local accounts)Off (SSO with their AD account)On (local accounts)
Advanced → Disconnected session kept for / Maximum session length30 min / 12 hSame

For a new Windows pool, the editor fills the OU, DNS servers, DNS suffix and RDP domain from Active Directory, and suggests "Allow Remote Desktop for" from the Guacamole groups (for example CORP\sde-vdi-users). Check them under Advanced before saving.

Save it. Watch the Desktops tab: the first desktop goes from Cloning through Windows setup, Renaming, Joining the domain, Checking domain trust, Granting Remote Desktop access and Waiting for Remote Desktop, to Spare. If it stops on a step, see Troubleshooting.

11. Give users access

A user may use a pool when they can see its connection in Guacamole. The easy way is the pool's Grant to Guacamole groups field: put the AD group's name there (for example sde-vdi-users). sde-vdi creates the Guacamole user group of the same name if it's missing, and grants it the pool. Guacamole matches LDAP group membership by name, so adding someone to the AD group gives them the pool. Taking a group off the field removes only that grant.

Or grant "<pool name>", in "Desktop Pools (open in SDE Remote)", by hand in Guacamole:

  • To a group: create a Guacamole user group with the same name as an AD group and grant the pool to it.
  • Per user: Settings → Users → the user (add them with the same username if they aren't listed) → tick the pool.

Users also need Remote Desktop rights on the desktops (4.3 or the pool setting).

12. The SDE Remote app

Use the current app (1.1.2, Windows or Linux):

  • Each pool shows as a DESKTOP POOL tile with "N ready" and a Connect button. With no spare, Connect shows "Preparing your desktop…" and keeps trying for up to 15 minutes.
  • Closing FreeRDP keeps the desktop for the pool's Disconnected session kept for (30 minutes by default). Reconnecting returns the user to the same session.
  • Guacamole administrators get Admin → Desktop pools. It opens the admin page, already signed in.
  • When a desktop refuses the sign-in, the app says "Windows refused the sign-in" and names the FreeRDP log.

13. Acceptance tests

  • Readiness: no Fix lines. Settings → Test connections: Proxmox, Guacamole and Guacamole entries all OK.
  • The first desktop reaches Spare without errors. Note the time it takes.
  • The desktop is in the OU in AD, and <name>.<domain> resolves from the gateway host.
  • A user with the grant sees the tile with "1 ready". Connect gives a desktop signed in as them, with no password prompt.
  • The next spare starts building straight away.
  • Closing FreeRDP and reconnecting within 30 minutes gives the same desktop.
  • A Guacamole-only account (for example guacadmin) is refused the pool with a message, and no desktop is taken.
  • Signing out of Windows deletes the desktop within a couple of minutes, and the pool refills.
  • Two users at once get different desktops. With the pool full, a third gets "No desktops free".
  • A non-admin can't open the admin page. Nothing at /sde-vdi/v1/ answers through the portal (deploy-sde-vdi.sh --check tests it).
  • The usage report (/report) shows the session under "Desktop pools" with the pool and desktop name.

14. Day-to-day operations

TaskHow
Update the imageBuild a new template version (template guide, section 11), then choose it as the pool's Gold template. Spares are replaced at once; desktops in use are replaced as users sign out.
More or fewer sparesPool → Spare desktops / Maximum desktops. Changes apply within seconds; extra spares are removed after 10 minutes.
A stuck or broken desktopDesktops → Delete now. The pool replaces it.
Who's on what, what happenedThe Desktops and Activity tabs. Full history: docker logs sde-vdi (AUDIT vdi-… lines) and the gateway's AUDIT authorize … vdi_….
Upgrade sde-vdigl -d sde-vdi && gl -s sde-vdi pulls :latest. Leases and pools survive (state volume).
Pause all changesSDE_VDI_PAUSED=true and restart: nothing is cloned or deleted, and handing out spares still works.
Busy timesPool → Spare desktops by time of day. Start a rule about 10 minutes before the rush, because a desktop takes that long to prepare.
Clean up ADReadiness → Active Directory clean-up → Scan. It lists computer objects whose names won't come back (the pool shrank, its name pattern or OU changed, or it was deleted). Tick and delete; their DNS records go too. Recycled desktops' objects are kept on purpose, because the next desktop of that name reuses them.
Restore the stategl -d sde-vdi, copy a file from data/state/backups over data/state/state.json, gl -s sde-vdi. Desktops created since that copy show as quarantined; delete them.
Rotate the Proxmox tokenpve-bootstrap-sde-vdi.sh --rotate-token on a node, put the new secret in the unit, restart it.

14.1 Hardening for live

  • Gateway API only from the gateway: SDE_VDI_V1_NETWORKS=172.16.0.0/12 (the docker networks; Readiness shows the address the gateway calls from). Through nginx, /v1 is always refused.
  • Join account delegated, never a Domain Admin (ad-bootstrap-sde-vdi.ps1 sets it up that way).
  • Proxmox certificate verified: SDE_VDI_PVE_CA_FILE instead of SDE_VDI_PVE_INSECURE.
  • Secrets file: chmod 600 on both units' enviroment files. Rotate the Proxmox token if its secret was ever shared.
  • Admin page: SDE_VDI_ADMIN_NETWORKS limited to the admins' subnets.
  • Backups: include /var/glitch-units/sde-vdi/data/state (with its daily copies) in the host backup.

15. Troubleshooting

SymptomCause and fix
Desktop stuck at "Windows setup"The template's unattend file doesn't skip OOBE. Add SkipMachineOOBE/SkipUserOOBE and release a new version (Windows guide § 8).
"domain join … could not be contacted"The desktop can't resolve the domain. Set the pool's DNS servers to the DCs.
Desktop stays at waiting-dns, or its name resolves to an old addressAn older computer object owns the DNS record, so the DC refuses the desktop's update (event 8018). sde-vdi deletes the record and re-registers it every 2 minutes; if the join account may not delete it, delete the A record in DNS Manager.
Stuck at "Checking domain trust", or users rejected with 0xC000018DThe DC's time or replication is broken. Fix the PDC's time; sde-vdi repairs the trust automatically after 3 minutes. If only pools on an SDE Network are refused with 0xC000018D, see Troubleshooting (Netlogon secure channel).
"Windows refused the sign-in", or FreeRDP closes straight after ConnectWrong password, an account Windows doesn't know, a broken trust, or no Remote Desktop rights on the desktop (set the pool's groups or a GPO). Event 4625 on the desktop gives the reason. On Linux, check RDP security is TLS, not NLA.
"… is an SDE-only account, so it can't sign in to the desktops in …"A Guacamole-only account (SDE_LOCAL_ACCOUNTS) tried a pool that passes the user's sign-in through. Sign in with a domain account.
An AD user can't sign in to the app, but a Guacamole-only user canThe user is outside Guacamole's ldap-user-base-dn, or an LDAP service account has expired (section 5).
Readiness: "DC clock" failsThe DC is more than 4 minutes out. Kerberos fails at 5. Fix the PDC's NTP source; on Proxmox the DC VM needs a Windows OS type.
Readiness: "Sign in to AD" failsWrong join password, or no LDAPS from the gateway host to a DC (port 636). Set SDE_VDI_AD_LDAP_HOST to a DC if the domain name doesn't resolve on the host.
A pool's Guacamole entry shows "grant: …"The service account can't create user groups or grant permissions. Give gua_srv "Create new user groups" or "Administer system".
"No desktops free"The pool is at its maximum. Raise it if the host has memory.
Pool shows "Can't add desktops"Read the message: template not found, no node with room, or a token permission. The Templates and Settings tabs help.
Clones fail or the host strugglesToo many clones at once: lower SDE_VDI_MAX_PARALLEL_CLONES (default 2) or add memory or I/O.

More problems, with the commands to look inside a desktop: Troubleshooting SDE VDI desktop pools.

16. Removing SDE VDI

  1. In the admin page, switch each pool off, wait for its desktops to drain, then delete the pool. Its Guacamole entry is removed too.
  2. Remove SDE_VDI_URL/SDE_VDI_SECRET from the gateway and restart it. Pool tiles disappear from the app.
  3. gl -d sde-vdi, remove the nginx block, and reload nginx.
  4. Optionally remove the Proxmox token, role and pools, and the AD join account and OU.

person people found this useful.