Por qué este proyecto Why this project

Este proyecto es más lúdico que los anteriores: lo he hecho porque me gusta Pokémon, y me apetecía montar algo así para poder jugar con amigos. No busca resolver un problema de trabajo ni de infraestructura crítica, sino usar lo que ya sé de sistemas y redes para algo que simplemente me apetecía tener funcionando.

This project is more playful than the previous ones: I built it because I like Pokémon, and I wanted to set something like this up to play with friends. It's not solving a work problem or critical infrastructure — it's using what I already know about systems and networking for something I just wanted to have running.

Visión general del proyecto Project overview

Objetivo: un servidor centralizado para la sincronización de partidas guardadas (archivos .sav) y un servidor de conexión/redirección DNS para partidas multijugador en emuladores como MelonDS.

Sistema operativo base: Debian.

Goal: a centralized server for syncing save files (.sav) and a DNS connection/redirection server for multiplayer games on emulators like MelonDS.

Base operating system: Debian.

Componentes de la arquitectura y su creación Architecture components and how I built them

Servicio de sincronización (Syncthing vía Docker Compose)

  • Despliegue mediante Docker Compose utilizando la imagen oficial syncthing/syncthing:latest.
  • Uso de la variable de entorno STGUIADDRESS=0.0.0.0:8384 para forzar la exposición de la interfaz web (GUI) en todas las interfaces de red.
  • Gestión de permisos de volúmenes locales en Debian (chown -R 1000:1000 /opt/syncthing) para resolver conflictos de escritura en los certificados SSL y archivos de configuración.

Sync service (Syncthing via Docker Compose):

  • Deployed with Docker Compose using the official syncthing/syncthing:latest image.
  • Used the STGUIADDRESS=0.0.0.0:8384 environment variable to force the web GUI to be exposed on all network interfaces.
  • Managed local volume permissions on Debian (chown -R 1000:1000 /opt/syncthing) to fix write conflicts on SSL certificates and config files.

Servicio de redirección para el juego multijugador (DNS local)

  • Implementación nativa con dnsmasq para evitar problemas de compatibilidad con contenedores o repositorios de GitHub obsoletos.
  • Configuración del archivo /etc/dnsmasq.conf para responder al test de conexión (conntest.nintendowifi.net) apuntando a la IP local, y redirigir el tráfico del juego (nintendowifi.net) hacia los servidores comunitarios (Kaeru/AltWFC).

Redirection service for multiplayer (local DNS):

  • Native implementation with dnsmasq, to avoid compatibility issues with containers or outdated GitHub repos.
  • Configured /etc/dnsmasq.conf to answer the connection test (conntest.nintendowifi.net) by pointing to the local IP, and to redirect the game's traffic (nintendowifi.net) to the community servers (Kaeru/AltWFC).

Conectividad externa y VPN mesh (superando la CG-NAT) External connectivity and mesh VPN (getting around CG-NAT)

  • Integración de Tailscale para saltar las restricciones de puertos y CG-NAT impuestas por el proveedor de internet (ISP).
  • Asignación de una IP fija virtual dentro de la red mesh (100.x.x.x) tanto para el servidor Debian como para los dispositivos remotos de los jugadores.

External connectivity and mesh VPN (getting around CG-NAT):

  • Integrated Tailscale to get around the port restrictions and CG-NAT imposed by the internet provider (ISP).
  • Assigned a fixed virtual IP within the mesh network (100.x.x.x) both for the Debian server and for the players' remote devices.

Flujo de funcionamiento paso a paso Step-by-step operation flow

Para el guardado en la nube

MelonDS guarda el archivo .sav → Syncthing en el PC local detecta el cambio → transfiere los datos de forma cifrada al servidor Debian a través del túnel de Tailscale → Debian mantiene la copia de seguridad centralizada.

For cloud saving: MelonDS saves the .sav file → Syncthing on the local PC detects the change → transfers the data encrypted to the Debian server through the Tailscale tunnel → Debian keeps the centralized backup.

Para el multijugador en línea

MelonDS apunta su DNS primario a la IP de Tailscale del servidor Debian → Debian valida la conexión Wi-Fi de la Nintendo DS emulada → redirige la partida a los servidores de la comunidad sin necesidad de abrir puertos en el router.

For online multiplayer: MelonDS points its primary DNS to the Debian server's Tailscale IP → Debian validates the emulated Nintendo DS's Wi-Fi connection → redirects the game to the community servers without needing to open any ports on the router.