Servidor web

Una herramienta básica para cualquier desarrollador web es la posibilidad de compartir un servidor local, o puerto, con cualquier persona o dispositivo. Un caso típico, estoy desarrollando un sitio dinámico en Django y quiero que mi cliente pueda ver los últimos avances. Lamentablemente aún no se ha desplegado el sitio en ningún servidor. En ese caso puedo levantar la aplicación en mi equipo local e indicar al cliente que acceda a una dirección que yo controlo (demo.ejemplo.com). Cuando el cliente termine de revisar los avances, podré cerrar el puente con el dominio y continuar mi trabajo. No es necesario desplegar los cambios ni crear un entorno de pruebas, todo se hace en el equipo local.

Para esta labor existen diferentes soluciones. La más popular es Ngrok, un servicio que posee una capa gratuita. Desde el terminal puedes crea un túnel seguro entre un puerto local de tu máquina y un dominio público generado por ellos. Lamentablemente debes pagar para poder personalizar el dominio, en caso contrario será aleatorio. Y otra debilidad es la privacidad. No debemos ignorar que todos los datos que se servirán atravesarán sus servidores.

En este tutorial te enseñaré cómo crea un túnel de un puerto local a un dominio público de tu control. Además, todos los datos se moverán a través de una conexión de tu propiedad.

0. Requisitos

Necesitarás disponer de algunos elementos previos para poder seguir este tutorial:

  • Servidor local: De ejemplo, levantaré con Python un sencillo servidor web en el puerto 9000. Puedes usar PHP, Apache, Django, Laravel, Node.js o lo que desees.
  • Servidor con una IP pública: Puede ser un VPS, un servidor dedicado o un ordenador personal. ¿Tienes una Raspberry Pi con Noip? ¡Perfecto!
  • Posibilidad de crear una conexión SSH con el servidor: Será esencial para crear el túnel.
  • Dominio: Puede ser un dominio de primer nivel (TLD) o un subdominio. En mi caso usaré el subdominio demo.ejemplo.com.
  • Servidor web en el servidor: Como Nginx o Caddy.

Si ya dispones de todo ello. ¡Empecemos!

1. Crear un documento HTML

Como ejemplo, prepararé un documento HTML básico llamado index.html con el siguiente contenido:

<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <title>Hola mundo</title>
</head>
<body>
    <h1>DEMO</h1>
    <p>Este es un servidor local compartido en un dominio público.</p>
</body>
</html>

2. Levantar un servidor local

Para levantar un servidor local de ejemplo usaré Python mediante un comando.

python3 -m http.server 9000

Debes lanzarlo en la misma carpeta donde se encuentra el archivo index.html. Si todo ha ido bien, podrás acceder a la página web desde la dirección http://localhost:9000. Si no funciona, comprueba que el puerto 9000 no está ocupado por otro proceso.

Ya disponemos de un servidor local emulando un servidor web o una aplicación web (Django, Laravel, Node, Ruby on Rails, etc). Es hora de preparar el dominio.

3. Configurar DNS

En mi ejemplo, el servidor esta expuesto con una IP pública 1.2.3.4 y el dominio que quiero utilizar es demo.ejemplo.com. Para que el dominio apunte correctamente he creado un registro A del subdominio demo.ejemplo.com a la dirección 1.2.3.4. Si no sabes cómo hacerlo, puedes consultar la documentación de tu proveedor de dominios. Es un paso que debes resolver por tu cuenta.

Con el registro A creado, ya podemos configurar el servidor web del servidor.

4. Configurar el servidor web del servidor

Ahora debemos configurar el servidor web del servidor para que apunte al puerto local.

Te doy 2 opciones: Nginx o Caddy. Si usas otro servidor web, deberás buscar la forma de configurarlo por tu cuenta.

4.1 Nginx

Si usas Nginx, debes crear un archivo llamado demo.ejemplo.com en la carpeta /etc/nginx/sites-available/, con el siguiente contenido:

server {
    listen 80;
    listen [::]:80;

    server_name demo.ejemplo.com;

    location / {
        proxy_pass http://localhost:9000;
    }
}

Y luego crear un enlace simbólico en la carpeta /etc/nginx/sites-enabled/:

sudo ln -s /etc/nginx/sites-available/demo.ejemplo.com /etc/nginx/sites-enabled/demo.ejemplo.com

Por último, reiniciar el servidor web:

sudo systemctl restart nginx

4.2 Caddy

Si usas Caddy, debes crear un archivo llamado Caddyfile en la carpeta /etc/caddy/, con el siguiente contenido:

demo.ejemplo.com {
    reverse_proxy localhost:9000
}

Y luego reiniciar el servidor web:

sudo systemctl restart caddy

5. Crear un túnel SSH

Ya hemos llegado al último paso. En nuestro equipo local crearemos el túnel SSH encargado de conectar el puerto local con el puerto público.

ssh -R 9000:127.0.0.1:9000 usuario@ejemplo.com
  • -R: Indica que el puerto remoto se redirigirá al puerto local.
  • 9000: El primero es tu puerto local y el segundo es el puerto del servidor remoto. Una renvío el puerto 9000 de mi equipo local al puerto 9000 del servidor remoto.
  • 127.0.0.1: Dirección del servidor local.
  • usuario: Usuario del servidor.
  • ejemplo.com: Dirección del servidor.

Desde tu punto de vista, conectarás con el servidor por SSH como siempre. Aunque no veas muestras de ello, el túnel se ha creado correctamente.

Puedes mejorar el comando SSH con la opción -f para que se ejecute en segundo plano y -N para que no ejecute ningún comando en el servidor.

ssh -R 9000:127.0.0.1:9000 -f -N usuario@ejemplo.com

Ahora podrás acceder a la página web desde la dirección http://demo.ejemplo.com. ¡Enhorabuena!

Recuerda que debes mantener la conexión SSH abierta para que el túnel siga funcionando. Si cierras la conexión, el túnel se cerrará y no podrás acceder a la página web. Igualmente, si cierras el servidor local, el túnel también se cerrará.

Espero que este tutorial te haya sido de utilidad.