I configured a Docker container that successfully compiles and runs a fresh install of the latest ServUO (publish 57 at the time of writing this) on my Synology NAS. It reads the necessary game files from a folder within ServUO, and I can connect to it fine using the EC Launcher tool.

However, whenever I try any variant of the classic client it ends up crashing after selecting the shard (Razor/RazorEnhanced + normal client), or it gets stuck on the "Login to Shard" step (ClassicUO with or without ClassicAssist) and does not reach character select, which ServUO normally mentions in its console.

I'm somewhat at a loss as to why this occurs. Because EC works I thought maybe there are some game files missing, but even when I compile with the full client it doesn't change anything. Does anyone know what I'm missing? I've included some technicals below.


There's nothing particularly special about how the Docker container is set up, but I'll include both the Dockerfile and docker-compose.yml file here just in case it would matter:

Dockerfile:
FROM ubuntu:20.04

RUN apt-get update && apt-get install -y wget && \
    wget https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb && \
    dpkg -i packages-microsoft-prod.deb && \
    apt-get update && \
    apt-get install -y apt-transport-https && \
    apt-get install -y dotnet-sdk-5.0 zlib1g-dev mono-complete make

RUN mkdir /servuo /game_files
WORKDIR /servuo

EXPOSE 2593

docker-compose.yml:
services:
  servuo:
    build:
      context: .
    restart: always
    volumes:
      - ./servuo:/servuo
      - ./game_files:/game_files
    ports:
    - "2593:2593"
    command: make

volumes:
  servuo: {}
  game_files: {}

Both the servuo and game_files directories are set through Synology's Docker UI. I went into the container and can verify they map correctly.

The game files ServUO was compiled with:
uo-game-files.jpg
 
Sorry, no experience with docker.. But some suggestions...
- consider redirecting the output of servuo to file e.g. modify the Makefile (mind the required 'tab' characters)
${CURPATH}/${EXENAME}.sh | tee run.log
maybe it helps in seeing where/what happens
- can it be that there are problems with (write) access rights to files?
- as docker (and the NAS) are a different machine(?), there have been issues with the world save (selection based on machine cores etc)
- client files, not sure if it looks in the gump or art files for picture sizes, depending one extra's cliloc info might be used too
- I dont think you need the ...x.mul and ...x.uop
 
First of all, thanks for your reply @Max! Answers inline; no solution yet but with your checklist of suggestions I can continue to tinker. If I get it fixed, I'll comment in this thread again.

- as docker (and the NAS) are a different machine(?), there have been issues with the world save (selection based on machine cores etc)
Hmm, connecting with the ECLauncher tool I can play and trigger world saves that persist just fine. I'm not too familiar with Docker's inner workings, but there doesn't seem to be an issue there in my case.

- can it be that there are problems with (write) access rights to files?
This might be something to verify. I mean the EC can play, but perhaps the classic client expects more liberally assigned rights. I'll tinker with this and see if it's the culprit.

- client files, not sure if it looks in the gump or art files for picture sizes, depending one extra's cliloc info might be used too
- I dont think you need the ...x.mul and ...x.uop
I'll include the cliloc files and recompile. If I recall I went off a comment on what client files to have available in ServUO's source code, but it's entirely possible I missed a particular type of files here.
 
EC works fine regular client not. Seems a lot should work in that case.
Can you still access the shard with EC after trying the regular client? (or did it crash/get stuck somehow).
So its the combination of docker and classic client, the server does work on windows/linux?
Seems to become code related, as access etc is expected to work. I expect you do need to get a view on on the console output.
 
@Hybrid - do you have a Linux virtual machine or something you can try your configuration on, just for testing? From what I've encountered, this appears to be some kind of issue with Docker networking and the ClassicUO client.

I created a Ruins And Riches server (RunUO base) which I run via Mono in a Fedora VM. If I run the server on a VM directly, ClassicUO connects just fine. If I run that same configuration in a container, ClassicUO lets me authenticate, select my server then hangs when attempting to retrieve the character list. I finally gave up and just went with a VM, but I understand that won't be an option if you want to run it from your Synology box.
 
@Hybrid - do you have a Linux virtual machine or something you can try your configuration on, just for testing? From what I've encountered, this appears to be some kind of issue with Docker networking and the ClassicUO client.
Sort of; I ran it on a DigitalOcean droplet just fine, but I use those for work which is less than ideal.

It's somewhat encouraging that I'm not the only one that faced a similar problem, but if it's a technical thing between containers and the way ServUO accepts connections I may have to give up on the idea.

Can you still access the shard with EC after trying the regular client? (or did it crash/get stuck somehow).
Yes, EC works every time, but any variant of the classic client / ClassicUO / Orion / ... does not.

I also went through your previous checklist, but none of the given suggestions seemed to make a difference.

So its the combination of docker and classic client, the server does work on windows/linux?
Yep, seems to be the case. If you read @EmptyBasket's response, that's what I'm facing here. I tried running the server outside the container to verify on both a windows and a linux host, and that does work. Inside the Docker container, it no longer does. Synology is pretty particular about what it can or can't run, which is why a Docker container seemed ideal. I've yet to try and install mono standalone (and to be honest; I'd rather not).

Seems to become code related, as access etc is expected to work. I expect you do need to get a view on on the console output.
It's a stock ServUO with all your default config settings. The console doesn't say much, apart from my client making a connection, then immediately disconnecting. No mention of missing client files or anything. In the client I just end up being stuck on "Verifying Account" until it times out. ¯\_(ツ)_/¯

Thank you both for the replies.
 
Hmm.. far from ideal, my next step would be to add prints into the code to extend the console output to see where the connection flow bails out.
 
@Hybrid - It has been a few months but I got it to work via a PR I found on the ServUO repo.

Check out this MR here: ServerListMap: ServerList selection by matching CIDR of remote address by ptgeorge · Pull Request #4955 · ServUO/ServUO

I used the GitHub CLI to checkout the specific PR via gh pr checkout 4955

Once I had the code, I installed the dotnet-sdk-5.0 package on Fedora 34 then performed the build via dotnet build. Previously I used mcs to build the package but I came across this issue - map.cs error compiling - and switched to `dotnet build`.

Next, I set configured Config/DataPath.cfg. I map my files to /data in the container, so my CustomPath line looks like this:
CustomPath=/data/uo_data/files

Then I ran the container like so (for testing): podman run -it --name=servuo -p 2593:2593 -v ./ServUO:/data:z docker.io/library/mono:6.12 /bin/bash

After launching mono ServUO.exe, I ran into the expected connection problem. This brought me to test the changes in that PR. I edited Config/ServerListMap.xml and added an entry to match the container internal IP address and a destination of my VM's real IP address (I'll use 192.168.100.10 here). For example: ' <entry cidrmatch="10.0.2.100/32" destination="192.168.100.10"/>'. I know the container will always have an IP address of 10.0.2.100 if I run it as a rootless podman containers, so I put a /32 single host cidrmatch, but put whatever range works for you.

When you connect, you should see console output like '
ServerListMap: 10.0.2.100 matches 10.0.2.100/32; using destination 192.168.100.10' and most importantly, the client will actually connect.

I still need to build a real containerfile but for now, I'm quite thrilled the connection actually works :)
 
@Hybrid - It has been a few months but I got it to work via a PR I found on the ServUO repo.

Check out this MR here: ServerListMap: ServerList selection by matching CIDR of remote address by ptgeorge · Pull Request #4955 · ServUO/ServUO

I used the GitHub CLI to checkout the specific PR via gh pr checkout 4955

Once I had the code, I installed the dotnet-sdk-5.0 package on Fedora 34 then performed the build via dotnet build. Previously I used mcs to build the package but I came across this issue - map.cs error compiling - and switched to `dotnet build`.

Next, I set configured Config/DataPath.cfg. I map my files to /data in the container, so my CustomPath line looks like this:
CustomPath=/data/uo_data/files

Then I ran the container like so (for testing): podman run -it --name=servuo -p 2593:2593 -v ./ServUO:/data:z docker.io/library/mono:6.12 /bin/bash

After launching mono ServUO.exe, I ran into the expected connection problem. This brought me to test the changes in that PR. I edited Config/ServerListMap.xml and added an entry to match the container internal IP address and a destination of my VM's real IP address (I'll use 192.168.100.10 here). For example: ' <entry cidrmatch="10.0.2.100/32" destination="192.168.100.10"/>'. I know the container will always have an IP address of 10.0.2.100 if I run it as a rootless podman containers, so I put a /32 single host cidrmatch, but put whatever range works for you.

When you connect, you should see console output like '
ServerListMap: 10.0.2.100 matches 10.0.2.100/32; using destination 192.168.100.10' and most importantly, the client will actually connect.

I still need to build a real containerfile but for now, I'm quite thrilled the connection actually works :)
Sorry for the late reply, but many thanks for pointing me to that PR and putting in the effort of writing a summary! I'll only be able to actually do something with it in a few weeks' time, but I'm excited to try it out and make it work.

I will report back when I got to work on it.
 
@EmptyBasket Another couple of turbulent months, but I finally got to get back to this. And I got it to actually work as per your suggestion of that PR! I can now connect using ClassicUO + ClassicAssist to a ServUO server running in a Docker container on a Synology NAS. As a UO vet of 20+ years, that's pretty amazing to me. And frankly, all things considered, with minimal configuration.

As you explained, literally the only thing I needed to do was add my CIDR mapping in Config/ServerListMap.xml. For Docker containers it's usually a variant of 172.17.x.x. For posterity, this is what's now in my Config/ServerListMap.xml file.

XML:
<?xml version="1.0" encoding="UTF-8"?>
<serverListMap>
    <!-- entry elements define a remote cidr address match that maps to a destination
    cidrmatch   String  IP CIDR to match against the remote address, such as 192.168.1.0/24
    destination String  Destination IP to use if matched
    -->
    <!-- Example 1 - Single address match where NATing is insufficient / misconfigued (SSH tunnel + docker)
    <entry cidrmatch="172.18.0.1/32" destination="127.0.0.1"/>
    -->
    <!-- Example 2 - Local network match where NAT'ing is insufficent / misconfigured (docker)
    <entry cidrmatch="192.168.1.0/24" destination="192.168.1.100"/>
    -->
    <entry cidrmatch="172.17.0.2/24" destination="192.168.0.184"/>
</serverListMap>

So thank you to everyone who took the time to respond to this over the past 6 months!
 
Back