Migrating from Thinfinity
Your program keeps sending the same request (/ws/oturl/get) and gets the same answer. Only the server address changes; everything else is set up on the Anping server.
What stays the same
| Same | Details |
|---|---|
| Path | /ws/oturl/get, with the values in the address (GET). |
| Options | Every option's name, type and default (differences). |
| Answer | /oturl.html?key=..&pass=.., which your program puts after the server address. |
| Modes | Name a model; a model plus your own options (overrideDefaults=true); or no model. |
What changes
| Item | With Anping |
|---|---|
| Server address | The Anping address, such as https://anping.example.com. |
| API key | One of Oturl:ApiKeys: a new key, or the value you send today if only the address should change. |
| Models | Each Access Profile your program names becomes a computer setup in Anping. Its Id is that same model value, and its settings go under Targets:N:Oturl:<parameter>. |
computer in the request | Your program can only name computers listed in Oturl:AllowedComputers. |
| Showing it in your page | Your site's address in Oturl:FrameAncestors. |
| Public name check | Your public name in AllowedHosts. |
| Computer certificates | Your sign-in is checked first (NLA), and each computer must prove who it is with a trusted or pinned certificate. The one Windows makes for itself needs a pin (below). |
| Production checks | Anping won't start with the development key, a key under 32 characters, test pages or a missing load balancer setting (settings). |
A model, step by step
Say your program sends model=sales-desktop, a profile that opens one program window (RemoteApp) at a fixed size. On the Anping server you write:
Targets__0__Id=sales-desktop
Targets__0__Name=Sales
Targets__0__Host=sales-rdp.corp.example
Targets__0__Port=3389
Targets__0__Domain=CORP
Targets__0__Username=sales-app
Targets__0__Password=<from your secret store>
Targets__0__Oturl__startprg=2
Targets__0__Oturl__command=||SalesApp
Targets__0__Oturl__resolution=fixed
Targets__0__Oturl__width=1280
Targets__0__Oturl__height=800
Targets__0__Oturl__clipboard=falseLeave out Username and Password and the link page asks each user; or your program sends them. A setting with a wrong value shows up in the log when Anping starts.
Settings that are not parameters, and Thinfinity's names
Name(shown in the toolbar),Security,CertFingerprints(certificates),KeyboardLayout,AllowCopy/AllowPaste(one clipboard direction),ClipboardLineEndings,AllowUpload/AllowDownload,AllowAudio/AllowPrinting,AllowProgramOverride,TimeZone,ClientName,Touch,WindowsIme(all settings). TheAllowflags are limits a request can't raise.- If programs inside the remote session look for Thinfinity's names, set
Oturl:DefaultDiskNametoThinDiskandOturl:DefaultPrinterNameto the printer name they expect.
Access Profile to model
| In your Access Profile | Where it goes in Anping (same names as the link options) |
|---|---|
Profile key (model) | Targets:N:Id, the same value, exact case. |
| Name | Targets:N:Name, shown in the toolbar. |
| Computer, port | Targets:N:Host, Targets:N:Port. |
| Saved user name and password | Targets:N:Username, Password, Domain; left out, the link page asks. |
| Security, early sign-in check (NLA), certificate | Targets:N:Security (default nla), Targets:N:CertFingerprints; Targets:N:Oturl:disablenla. |
| Display | Targets:N:Oturl:resolution, width, height, bpp, imagequality. |
| Experience | Targets:N:Oturl:desktopbackground, visualstyles, menuwindowanimation, fontsmoothing, showwindowcontent, desktopcomposition. |
| Program | Targets:N:Oturl:startprg, command, cmdargs, directory.MoreA model that starts a program keeps it, also withoverrideDefaults=true; for Thinfinity's behaviour set Targets:N:AllowProgramOverride. |
| Keyboard | Targets:N:Oturl:unicodekeyboard, keyboardlayout; the session's layout: Targets:N:KeyboardLayout. |
| Console session, compression | Targets:N:Oturl:console, wscompression. |
| Virtual machine (Hyper-V), server farm (RD Connection Broker) | Targets:N:Oturl:desttype, destinfo. |
| Shared folder, clipboard, sound, printer | Targets:N:Oturl:diskenabled, diskname, diskautodownload, clipboard, soundenabled, soundquality, printer*.MoreTo limit one direction or forbid a feature:AllowUpload, AllowDownload, AllowCopy, AllowPaste, AllowAudio, AllowPrinting. Printing is off by default (Guacd:Printing, below). |
| Video compression (H.264), recording, pools, load balancing, permissions | No equivalent: dropped in the move, without any error. Your program decides who gets a link.MoreSession recording, pools or load balancing over several computers, and permissions (which users or groups may use the profile). Sessions simply run without them. |
Anping ignores a name under Targets:N:Oturl that isn't a link option, and warns about it when it starts.
Parameter mapping
Every option keeps its name, in the request and in a model's Oturl settings. What each one does and how well it works: parameter table. Anping also accepts format=json and POST.
Known differences
| Topic | What is different in Anping |
|---|---|
| Colour depth | 32-bit colour by default (Thinfinity: 16). For 16, set Targets__N__Oturl__bpp=16.Technical detailWithoutbpp: 32-bit colour with the RDP graphics pipeline. Set the 16 on the model, or send bpp=16 with overrideDefaults=true: with model alone, connection parameters in the request are ignored. |
model | Must match a model's Id exactly, upper and lower case included. Option names may use any case. |
imagequality | 2 and 3 behave like 1. |
directory | Only for single program windows (RemoteApp, startprg=2). |
unicodekeyboard | Typed text is right as long as the remote session uses the model's keyboard layout. |
diskname, diskautodownload | The shared folder is called Anping by default. Saved files come to the browser once closed; not yet checked with Windows.Technical detailFrom anywhere in the drive if the Anping server runs on Linux, otherwise only from the drive'sDownload folder. A file over Files:MaxUploadBytes stays on the drive. |
printerenabled | Printing is off by default: the link opens without a printer, and the dry run says why. Turning it on (Guacd:Printing) needs a desktop engine with Ghostscript, which is AGPL-3 or a commercial license from Artifex. |
printersetasdefault=false, printerdriver | Not possible with the desktop engine (guacd from Apache Guacamole 1.6.0). |
| Sound | Plays in any browser that can play sound from a page (Web Audio), after the first click or key press. |
| Reload, drops | Same browser: 10 minutes after a disconnect, automatically 60 seconds after a drop. Others: the used message. |
| Connections | One connection per link; a newer one from the same browser takes over at once. |
| Errors | A plain-text answer: an error number (HTTP status) and a short reason (errors). |
| Time zone, computer name, touch | No link options for these; set them per model (TimeZone, ClientName, Touch).Technical detailBy default every session gets the browser's time zone (with a Windows policy, Windows computers), the client nameAnping- and 8 characters of the link id, and touch as a mouse. |
| Session limits | 60 minutes without input, 720 after the start; End closes a link for good (lifetime).MoreSessions:IdleTimeoutMinutes and Sessions:MaxDurationMinutes; 0 turns a limit off. |
| Restart | Forgets every link and ends every session; users need a new link.MoreUsed or not. The page says the service restarted and that a new link is needed. |
| Model limits | A model's limits (Allow flags) and its program stay, even with overrideDefaults=true.Technical detailTheAllow flags are ceilings a request can't raise; a model that starts a program keeps it unless AllowProgramOverride is set (Thinfinity lets the request change it). |
| Wrong passwords | Limited per link and per network (sign-in limits). |
| Certificates | Your sign-in is checked first (NLA), and the computer needs a trusted or pinned certificate (below). |
| Several Anping servers | A link opens only on the Anping server that made it (deploying). |
| Not yet tested | Virtual machines (Hyper-V), server farms (RD Connection Broker, RD Session Host), single program windows (RemoteApp) on a real server, and Windows other than Server 2025.Technical detailHyper-V isdesttype=VMID, the RD Connection Broker desttype=RDS. Also: keyboard layouts other than US English; time zone, client name and native touch on Windows; the shipped Safari and Firefox apps (the automated tests use their engines), and a reload of an embedded page in Firefox and Safari. |
Computer certificates
A certificate is how a Windows computer proves who it is. Without that check, someone in between could pretend to be the computer and catch the passwords users type. So the certificate Windows makes for itself is refused until you do one of these for each computer:
| Way | How |
|---|---|
| 1 Pin it | Read its fingerprint (SHA-256) where the Anping server runs: dotnet Gateway.dll rdp-fingerprint host[:port]. Check it on the computer itself, then set Targets__N__CertFingerprints__0=sha256:...Technical detailIn the development stack:scripts/rdp-fingerprint.sh host[:port]. For a computer named in links: Oturl__ComputerSettings__N__Computer=<host> and Oturl__ComputerSettings__N__CertFingerprints__0=sha256:... Windows renews its self-signed certificate when it expires (the tool prints the date): add the new fingerprint before then, and keep the old one until no computer presents it. |
| 2 Or give it a certificate | One for the name in Host (or computer), from a certificate authority (CA) the desktop engine trusts.Technical detailAn enterprise (Active Directory) authority has to be added to that image, which comes with Anping's own engine image; until then, pin. |
- A computer without the early sign-in check (NLA; some non-Microsoft servers):
Securitytls, ordisablenla=truein the link. The certificate is still checked. - Refused, the user sees The remote desktop service could not verify the remote computer's certificate, so it did not connect.; Anping's log names the computer, what it expected and the fingerprint it got.
IgnoreCertturns the check off. Only for development and lab servers; anywhere else Anping won't start.
Dry run with your real requests
Before you switch, replay the requests your program sent to Thinfinity. /ws/oturl/check tells you what /ws/oturl/get would do, without making a link (dry run).
ANPING_API_KEY=... node scripts/oturl-replay.mjs --gateway https://anping.example.com requests.txt| Step | What the replay tool does |
|---|---|
| Reads | One request per line: a web address or path with /ws/oturl/get?..., a log line that contains one, the part after ?, or POST <form body>.MoreBlank lines and# comments are skipped. |
| Keeps secrets out | Removes the file's API keys, hides passwords and user names, sends your key (ANPING_API_KEY) in the request body (POST), and never prints the lines it reads. |
| Prints | A row per request, then totals over the file.MoreEach row: accepted or refused, mode, model, first problem. Then every problem, parameter without effect and difference from Thinfinity, counted over the file.--json prints each answer. |
| Then | Fix what is refused, in your program or the model, read the rest, then switch the address. |
Parallel run and rollback
To roll back, point the address back to Thinfinity. Links already handed out open only on the server that made them and expire after expires minutes; open Anping sessions last until the user disconnects.
Step by step
- Keep Thinfinity running and unchanged while you set up Anping next to it.
- Put the host name and API key in your program's configuration.
- Replay a few days of requests with the dry run; fix what it reports.
- Keep sending GET (values in the address) while Thinfinity is your way back: both accept the same request.
- Move a pilot group first (one model, or a few users) and run the tests below with them.
- After cutover, switch to POST (Anping only): the API key stays out of URLs and logs.
Checklist
Deployment 7
- Anping and its desktop engine (guacd) run together in one copy, with file storage set as
Files:DriveRoot(Deploying). - Anping is reached over https with a valid certificate, through a load balancer that lets live connections (WebSockets) through.
AllowedHostshas the public name;ForwardedHeaders:KnownNetworksthe load balancer's network (orForwardedHeaders:NoProxy=true).- It runs in production mode (the default) and starts: no development key, test pages or invalid setting.
ConnectionLog:Pathis storage only Anping uses;/readyzanswers 200.- Allow time zone redirection on the Windows computers, if users should see their own time zone (Windows computers).
- One Anping server per address (a link opens only where it was made): per region, its own address, and your program asks the Anping server whose address it hands out. Several copies behind one address need a shared link store, which is coming.
Anping server settings 5
Oturl:ApiKeysfrom a secret store, 32+ random characters each (openssl rand -hex 32).- One computer per model, same
Idand case, with itsOturlsettings; no startup warning. Oturl:AllowedComputerslists everycomputeryour program sends;Oturl:FrameAncestorsevery embedding origin (if any).- Every computer's certificate trusted or pinned (above); no
IgnoreCert. - The load balancer doesn't log the part after
?for/ws/oturl/get,/ws/log,/oturl.html.
Your program 4
Test 6
- The dry run accepts every request, or you know why not.
- Every model opens its desktop (a different id, even in case, gets 400
Unknown model.). - A link opens; a reload reconnects; another browser shows the used message.
- Your parameters behave as set: size, program, clipboard, drive, sound, and the printer if you turned printing on.
- Embedded: the iframe shows the desktop; Reconnect works after a disconnect.
- The helpdesk has the user help and can read the connection log.