How can I Activate SSL for my WebGL client to work with Netcode server, while being hosted in HTTPS pages (like Itch.io)

I got it working, it was way more work than I anticipated. the way everyone goes around thi sproblem by using relay and lobbies is very mediocre, it’s basically a series of workarounds that require a lot of network bandwidth, creates race conditions also, in summary, it’s a mess. I hope you guys manage to get the multiplay sorted out because using tools like lobby to get around sharing the relay code forces developer to build a terrible network architecture, not scalable at all. Basically, if you think of the architecture of this thing, it’s using relay as a reverse proxy and lobby as an improvised messaging queue. WebGL is a very prominent format for many things, and let’s not set aside the amount of technical debt this adds to the users of Unity. There is a ridiculous amount of posts about this very subject to treat this as a nice to have.

To anyone in the future having htis issue, this is how you setup the server in Multiplay to use relay and WSS:

protected async Task<string> InitializeRelayServer()
    {
        await UnityServices.InitializeAsync();
        await AuthenticationService.Instance.SignInAnonymouslyAsync();

        Allocation allocation = await RelayService.Instance.CreateAllocationAsync(3);
        string joinCode = await RelayService.Instance.GetJoinCodeAsync(allocation.AllocationId);

        Debug.Log($"Relay server started with join code: {joinCode}");
        //If you use Relay SDK instead of Multiplayer, this method changes, there are many examples in the internet of that specific case.
        var relayServerData = AllocationUtils.ToRelayServerData(allocation, "wss");

        NetworkManager.Singleton.GetComponent<UnityTransport>().SetRelayServerData(relayServerData);
        NetworkManager.Singleton.StartServer();
        return joinCode;
    }

...
            string relayJoinCode = await InitializeRelayServer();
            var lobbyData = new Dictionary<string, DataObject>();
            lobbyData.Add("relayCode", new DataObject(
                visibility: DataObject.VisibilityOptions.Public,
                value: relayJoinCode,
                //Store it in a free string slot in your lobby
                index: DataObject.IndexOptions.S3));
            var serverConfig = MultiplayService.Instance.ServerConfig;
            try
            {
                //treat your multiplayer data, decide on game modes, or do whatever you do with it
                    ...
                    CreateLobbyOptions createLobbyOptions = new CreateLobbyOptions();
                    createLobbyOptions.Data = lobbyData;
                    var matchmakingTicket = JsonConvert.DeserializeObject<MatchData>(payloadJson);
                    lobby = await LobbyService.Instance.CreateLobbyAsync(matchmakingTicket.MatchId, 3, createLobbyOptions);
                serverQueryHandler = await MultiplayService.Instance.StartServerQueryHandlerAsync(2, "WarringTriad", "Random", "", "");
                NetworkManager.Singleton.OnClientDisconnectCallback += OnClientDisconnect;
                NetworkManager.Singleton.OnClientConnectedCallback += OnClientConnect;

                if (serverConfig.AllocationId != "")
                {
                    Debug.Log("Server Started!");
                }
            }

            await MultiplayService.Instance.ReadyServerForPlayersAsync();

On the client side, you need a retry method to get around the race condition of clients tryuign to access the lobby before it has been created:

//You call this method on the update to receive updates from the matchmaking. I won't go into detail of how to use matchmaking, there are other tutos for that
public async void PollMatchmakerTicket()
    {
        TicketStatusResponse ticketStatusResponse =
            await MatchmakerService.Instance.GetTicketAsync(createTicketResponse.Id);

        if (ticketStatusResponse != null)
        {
            if (ticketStatusResponse.Type == typeof(MultiplayAssignment))
            {
                MultiplayAssignment multiplayAssignment = ticketStatusResponse.Value as MultiplayAssignment;

                switch (multiplayAssignment.Status)
                {
                    case MultiplayAssignment.StatusOptions.Found:
                    {
                        Debug.Log("Found!");
                        createTicketResponse = null;
                        QueryForServerLobby(multiplayAssignment.MatchId);
                        break;
                    }
                    case MultiplayAssignment.StatusOptions.InProgress:
                        break;
                    case MultiplayAssignment.StatusOptions.Failed:
                    {
                        Debug.Log("Failed!");
                        createTicketResponse = null;
                        waitingForOpponetGameObject.SetActive(false);
                        break;
                    }
                    case MultiplayAssignment.StatusOptions.Timeout:
                    {
                        Debug.Log("Timed out...");
                        createTicketResponse = null;
                        waitingForOpponetGameObject.SetActive(false);
                        break;
                    }
                }
            }
        }
    }

    private void QueryForServerLobby(string matchId)
    {
        //This is my retry mechanism, the loading screen shows a spinner and then retries an awaitable method with a delay of 2 seconds between each attempt, receiving the matchId as parameter for the awaitable method
        StartCoroutine(loadingScreenController.ExecuteRetryableActionWithData(ConnectToServerLobby, (response) => { }, new List<string>{matchId}));
    }

    //Lobby querying, startng relay client and connecting to relay server.
    private async Task<bool> ConnectToServerLobby(string matchId)
    {
        QueryLobbiesOptions options = new QueryLobbiesOptions();
        options.Count = 1;

        // Filter for lobby with matching Matchmaker ticket
        options.Filters = new List<QueryFilter>()
        {
            new(
                field: QueryFilter.FieldOptions.Name,
                op: QueryFilter.OpOptions.EQ,
                value: matchId)
        };

        QueryResponse lobbies = await LobbyService.Instance.QueryLobbiesAsync(options);
        string lobbyId = lobbies.Results.First().Id;

        Lobby lobby = await LobbyService.Instance.JoinLobbyByIdAsync(lobbyId);
        string relayCode = lobby.Data["relayCode"].Value;
        await JoinRelayServer(relayCode);
        return true;
    }

private async Task JoinRelayServer(string joinCode)
    {
        JoinAllocation joinAllocation = await RelayService.Instance.JoinAllocationAsync(joinCode);

        // Configure the transport with relay data
        var transport = NetworkManager.Singleton.GetComponent<UnityTransport>();
        transport.SetRelayServerData(AllocationUtils.ToRelayServerData(joinAllocation, "wss"));

        NetworkManager.Singleton.StartClient();
        Debug.Log("Client connected to Relay Server.");
    }