There is nothing worse than buying premium hardware and having your software treat it like a generic accessory.
I recently picked up a PS5 DualSense controller. It wasn’t cheap, but I bought it for a specific reason: that trackpad. I wanted to use the full capabilities of the controller, specifically for mouse input, while streaming.
However, I ran into a wall immediately. No matter what I did, my setup kept auto-detecting the DualSense as a standard Xbox Controller. This meant no trackpad support and missing button functionality.
I went down the rabbit hole of forums and documentation so you don’t have to. If you are running a similar stack, here is the fix that saves you the headache.
The Setup
Just for context, here is the hardware and software I’m running to play World of Warcraft:
Host: Virtual CachyOS running Sunshine
Client: MacBook (M4 Air) running Moonlight
Controller: PS5 DualSense
The Goal: Play WoW on the CachyOS host using the DualSense trackpad for mouse control and scrolling.
The Problem
Sunshine usually defaults to X360 (Xbox) emulation to ensure maximum compatibility, if not then Steam will. While great for most games, it kills the specific features that make the DualSense special. If you want the trackpad to work as a trackpad, you need the host to see the controller as a DualSense, not an Xbox gamepad.
The Solution
The fix came down to two specific steps: fixing a permission error on the Linux host and forcing Sunshine to recognize the correct controller type.
Step 1: Fix the Permission Error
First, we need to ensure the user has the right permissions to access the input devices.
sudo nano /etc/udev/rules.d/60-sunshine.rules
# sudo nano /usr/lib/udev/rules.d/60-sunshine.rules# Allows Sunshine to access /dev/uinputKERNEL=="uinput", SUBSYSTEM=="misc", OPTIONS+="static_node=uinput", TAG+="uaccess"# Allows Sunshine to access /dev/uhid (Added subsystem for persistence)KERNEL=="uhid", SUBSYSTEM=="misc", TAG+="uaccess"# Joypads (Broadened to ensure the tag hits before the name is fully registered)SUBSYSTEM=="hidraw", KERNEL=="hidraw*", MODE="0660", TAG+="uaccess"SUBSYSTEM=="input",ATTRS{name}=="Sunshine*",MODE="0660",TAG+="uaccess"
Next, we need to tell Sunshine to stop pretending everything is an Xbox controller.
Open your Sunshine Web UI.
Navigate to Configuration -> Input.
[Insert your specific steps here, likely setting “Gamepad Emulation” to “DS4” or using a specific flag]
Now restart Sunshine or do a full reboot. Test your controller, it should pop up in Steam now as well:
Screenshot
Happy Gaming! Hopefully, this saves you the hours of troubleshooting it took me. Now, back to Azeroth.
Bonus:
By the way, World of Warcraft with controller still has a long way to go, however I find that Questing, Farming and Delving are some activities one can easily do with a controller. I would not recommend Tanking, I am a main Guardian Druid and while really enticing due to “not that many buttons” tanking is too dynamic for controllers. PVP is extremely hectic, people will run through you to get behind you and you wont be able to turn that fast.
All in all, I guess you can get used to anything, theoretically you also have potential to win the lottery or become a rockstar, but usually a regular job is a more stable income – as is mouse and keyboard for WoW. This was a weird analogy. It’s late here 🙁
How I turned my server into a headless gaming powerhouse, battled occasional freezes, and won using Arch-based performance and open-source streaming.
Sorry for the clickbait, AI made me do it. For real though, I am gonna show you how to build your own stream machine, local “cloud” gaming monster.
There are some big caveats here before we get started (to manage expectations):
Your mileage may vary, greatly! Depending on your hard and software versions you may not have any of the problems I have had, but you may also have many many more
As someone new to gaming on Linux the whole “run an executable through another layer ob virtualization/emulation” feels wrong, but I guess does not make that much of a performance difference in the end.
If you guessed that this will be a huge long super duper long post, you guessed right… buckle up buddy!
Lutris (for running World of Warcraft.. yea I am that kind of nerd, I know.)
Preperation
Proxmox Host
This guide is specifically for my Hardware so again: Mileage may vary.
SSH into your Proxmox host as root or enter a shell in any way you like. We will change some stuff here.
nano/etc/default/grub
# look for "GRUB_CMDLINE_LINUX_DEFAULT" and change it to thisGRUB_CMDLINE_LINUX_DEFAULT="quiet amd_iommu=on iommu=pt amdgpu.mes=0 video=efifb:off video=vesafb:off"
Copy all the settings I have here, make sure you disabled the Pre-Enrolled keys, this will try to verify that the OS is signed and fail since most Linux distros aren’t:
Leave all the defaults but use “SSD emulation” IF you are on an SSD (since we are building a gaming VM you should be):
CPU needs to be set to host, I used 6 Cores, you can pick whatever (number of CPUs you actually have):
Pick whatever memory you have and want to use here I am going with 16GB, disable “Ballooning” in the settings, this disabled dynamic memory management, simply put when you run this VM it will always have the full RAM available otherwise if it doesnt need it all it would ge re-assigned which is not a great idea for gaming where demands change:
The rest is just standard:
🚨NOTE: We have not added the GPU, yet. We will do this after installation.
Installing CachyOS
Literally just follow the instructions of the live image. It is super simple. If you get lost visit the CachyOS Wiki but literally just click through the installer.
Then shut down the VM.
Post Install
You will want to setup SSH and Sunshine before adding the GPU. We will be blind until Sunshine works and SSH helps a lot.
# enable ssh sudosystemctlenable--nowsshd# install and enable sunshine sudopacman-Ssunshinelutrissteamsysetmctl--userenable--nowsunshinesudosetcapcap_sys_admin+p$(readlink-f $(which sunshine))echo'KERNEL=="uinput", SUBSYSTEM=="misc", OPTIONS+="static_node=uinput", TAG+="uaccess"'|sudotee/etc/udev/rules.d/85-sunshine-input.rulesecho'KERNEL=="uinput", SUBSYSTEM=="misc", OPTIONS+="static_node=uinput", TAG+="uaccess"'|sudotee/etc/udev/rules.d/60-sunshine.rulessystemctl--userrestartsunshine# had to run all these to get it to work wayland is a bitch
Sunshine settings that worked for me:
# nano ~/.config/sunshine/sunshine.confadapter_name=/dev/dri/renderD128# <- leave auto detect or change to yourscapture=kmsencoder=vaapi# <- AMD specificlocale=deoutput_name=0# <- depends on your actual dispslay # restart after changing systemctl --user restart sunshine
Edit the Firewall, CachyOS comes with ufw enabled by default:
# needed for sunshine and ssh of coursesudoufwallow47990/tcpsudoufwallow47984/tcpsudoufwallow47989/tcpsudoufwallow48010/tcpsudoufwallow47998/udpsudoufwallow47999/udpsudoufwallow48000/udpsudoufwallow48002/udpsudoufwallow48010/udpsudoufwallowssh
Before we turn off the VM we need to enable automatic sign in and set the energy saving to never. We have to do this because Sunshine runs as user and if the user is not logged in then it does not have a display to show, if the energy saver shuts down the “Display” Sunshine wont work either.
ScreenshotScreenshot
As a security person I really don’t like an OS without proper sign in. Password is still needed for sudo, but for the sign in none is needed. I recommend tightening your Firewall or using Tailscale or Wireguard to allow only authenticated clients to connect.
Now you will turn off the VM and remove the virtual display:
Screenshot
You need to download the Moonlight Client from here, they have a client for pretty much every single device on earth. The client will probably find your Sunshine server as is but if not you can just add the client manually (like I had to do).
This step is so easy that I didn’t think I needed to add any more info here.
Bringing it all together
Okay, now add the GPU to the VM, double check that it is turned off.
Select the VM -> Hardware -> Add -> PCI Device
Select your mapped GPU, ensure Primary GPU is selected, select the ROM-Bar (Important! This will help with the GPU getting stuck on reboot and shutdown, yes that is a thing). Tick on PCI-Express:
It should look something like this:
Now insert the HDMI Dummy Plug into the GPU and start the VM
You should now be able to SSH into your VM:
Screenshot
Testing
If you are lucky then everything works out of the box now. I am not lucky.
I couldn’t get games to start through Steam thy kept crashing, the issue seemed to be old / non-existent Vulkan drivers for the GPU.
Maybe that is why I have had issues? Who knows, it works now.
The rest is really simple:
Start Lutris
Add new game
Search for “battlenet”
Install (follow the instructions, this is important)
ScreenshotScreenshot
Once installed you need to add Battle.net App into Steam as a
Screenshot
Once you pressed play you can log in to your Battle.net Account and start:
Screenshot
Resolution: 4K (3840×2160)
Framerate: Solid 60 FPS
Latency: ~5.6ms Host Processing (Insanely fast!)
Codec: HEVC (Hardware Encoding working perfectly)
Wrapping Up: The 48-Hour Debugging Marathon
I’m not going to lie to you, this wasn’t a quick “plug-and-play” tutorial. It took me a solid two days of tinkering, debugging, and staring at terminal logs to get this setup from “broken mess” to a high-performance cloud gaming beast.
We battled through Proxmox hooks, fought against dependency hell, and wrestled with Vulkan drivers until everything finally clicked.
I honestly hope this post acts as the shortcut I wish I had. If this guide saves you even just an hour of the headaches I went through, then every second of my troubleshooting was worth it.
And if you’re still stuck? Just know that we have suffered together, and you are not alone in the Linux trenches! 😂
For my next experiment, I think I’m going to give Bazzite a spin. I’ve heard great things about its “out-of-the-box” simplicity and stability. But let’s be real for a second: Bazzite isn’t Arch-based. If I switch, I lose the sacred ability to drop “I use Arch, btw” into casual conversation, and I’m not sure I’m emotionally ready to give up those bragging rights just yet.
Anyway, thank you so much for sticking with me to the end of this guide. You made it!
Love you, cutiepie! ❤️ Byyyeeeeeeeee!
Manage Consent
To provide the best experiences, we use technologies like cookies to store and/or access device information. Consenting to these technologies will allow us to process data such as browsing behavior or unique IDs on this site. Not consenting or withdrawing consent, may adversely affect certain features and functions.
Functional
Always active
The technical storage or access is strictly necessary for the legitimate purpose of enabling the use of a specific service explicitly requested by the subscriber or user, or for the sole purpose of carrying out the transmission of a communication over an electronic communications network.
Preferences
The technical storage or access is necessary for the legitimate purpose of storing preferences that are not requested by the subscriber or user.
Statistics
The technical storage or access that is used exclusively for statistical purposes.The technical storage or access that is used exclusively for anonymous statistical purposes. Without a subpoena, voluntary compliance on the part of your Internet Service Provider, or additional records from a third party, information stored or retrieved for this purpose alone cannot usually be used to identify you.
Marketing
The technical storage or access is required to create user profiles to send advertising, or to track the user on a website or across several websites for similar marketing purposes.