Running a Matrix Synapse instance on Windows Server with IIS as a reverse proxy
This is my peak.

In this article I will show you all the problems I ran into and the steps I took to finally get a Matrix Synapse deployment running on a Windows Server. As far as I know, I am the only one who has done this. It took me around four hours to get it working.
I'd like to start off with saying that most of the hours were used to figuring out IIS. I'm very experienced with Caddy, so IIS was completely different to me. I am glad I got to learn a little more about IIS while doing this, but I think I will stick to Caddy for my servers (that aren't running on Windows Server)
Okay, let's start
The first problem I ran into (basically, use WSL)
The first thing I decided to do was to get Synapse running in Docker. I already had Docker running with the Windows Containers feature, but eventually I figured out that Synapse and Postgres don't run on the Windows Containers platform. So I had to spend some time installing WSL. Microsoft do not recommend running WSL for containers in production, but you kinda have to because most Docker containers only have a Linux image.
I'll leave you some links to getting WSL installed, it's not that hard in my opinion.
Install Linux Subsystem on Windows Server | Microsoft Learn
Using WSL 2 on Windows Server 2022 to run Linux containers - Microsoft Community Hub
It's been a while since I last installed WSL. When I got into wsl, my first course of action was to run apt update. However, I ran into some DNS resolution errors. To fix that, I just ran "wsl --shutdown" and then go back into WSL and it worked.
When I tried to run "sudo service docker start", it said it started Docker but when I ran "docker version" it said it wasn't running. I did some research and found out that there's something you need to change in Debian (I assume you're running Debian in WSL from now on, if you aren't, adapt accordingly). It has something to do with iptables. I think Docker expects iptables-legacy but Debian uses iptables-nft. You probably don't care about firewalls in WSL, if so we're the same because I don't care about it either (there is already a firewall on the host, dammit). Run "update-alternatives --config iptables" as root and select iptables-legacy. Then you can run "sudo service docker start", and it should work.
Then it was time to get Synapse running. I'm not going to go into detail on how I did this because it's basically the same as getting Synapse running on any Linux running Docker (that being said, make sure you set it up in WSL).
I chose to go with a delegated Synapse setup, because I don't want to expose my IP (and I think delegation is a better setup, anyway). Now we need to set up IIS, so lets go do that.
The part you've been waiting for (IIS setup)
You need to install some modules on IIS. The first (and probably most important) module is URL Rewrite, and then we need Application Request Routing. To be honest, I don't know why IIS doesn't come with a reverse proxy. It's 2023, most things run on a port, the age of PHP and CGI are over but I'm getting off-topic.
We need to create two websites in the IIS Manager. You can probably use a config file or use a command tool from IIS, but that's up to you to figure out (I don't know how to use them, and I'm not interested). One of the websites will work as the delegation front (or you can do this on your domain instead of a subdomain), and the other will be the Synapse deployment itself. For me, the Synapse deployment is neuron.odyssey346.dev and I have pain.odyssey346.dev as my delegation front. (I was actually going to do the reverse but I wasn't focusing while I was configuring so I had to do it like this instead)
Getting a certificate is something you should be able to do yourself, but I can recommend the Posh ACME client. I tried win-acme but it didn't quite work for me.
Make sure your websites have a certificate! If they don't, Matrix will not work properly.
Why don't we get started with the Synapse deployment? Go on your Synapse deployment site, go on URL Rewrite feature and add a reverse-proxy rule. Set the localhost IP of your Synapse deployment as the IP address to reverse proxy. That should be it for the Synapse deployment.
Setting up the delegation front is definitely the most fun. Go on the delegation site, go to "Content View" and press Browse. That's right, we're going to create files. Whereas web servers like Caddy have "response", we can create files in IIS. It's fun, don't worry. Create a .well-known folder, and inside it create a matrix folder. Inside of there create a "client.json". Put the following in client.json:
{"m.homeserver":{"base_url":"https://yoursynapsedeployment.tld:443"}}
Replace "yoursynapsedeployment.tld" with the domain pointed to your Synapse deployment. This will point clients to your Synapse. Now create a "server.json", and put the following in it:
{"m.server": "yoursynapsedeployment.tld:443"}
Do the same as before, replace yoursynapsedeployment.tld with the domain pointed to your Synapse deployment.
That's it for files. Go back in IIS Manager and refresh the site you are working on. You should see folders in the "Connections" sidebar for your site. Go on .well-known/matrix and switch to the Features View if you're in Content View. Go in HTTP Response Headers and add Content-Type: application.json and Access-Control-Allow-Origin: *, like this:
We do need to write some rewrite rules, though. So go back to the Features View home and go to URL Rewrite. Create a new rule, just choose the trailing slash rule and select the remove option. Now we need to create the rules to rewrite for example .well-known/matrix/client to .well-known/matrix/client.json. Add a new rule, choose blank and change "using" to "Exact Match". Set pattern to client, and set rewrite url to client.json. Save it, and do the same for server.
Once this is done, restart both sites by right clicking the sites in the Connections sidebar, going into Manage Website and hitting restart. Try connecting to your Matrix server from a client like Element now. If it doesn't work, it is most likely your Synapse configuration.
What I've learned
Using GUIs to configure a web server isn't all that bad but it's not the most portable solution ever. I've also learned that setting up Synapse takes some time, most of it was just me not understanding Linux permissions though.
I'll never peak like this again, and I think this might be the highest quality article I'll ever publish.
It was fun setting it up though!