
Servidor de alojamiento web compartido automatizado basado en Tor con soporte multi-versión de PHP, enrutamiento de correo electrónico, instancias Tor de auto-escalado y endurecimiento de seguridad integrado que incluye protección CSRF, CSP y claves onion cifradas.
Esta es una configuración para un servidor de hosting compartido basado en Tor. Se proporciona tal cual y antes de ponerlo en producción, debes realizar cambios según tus necesidades. Este es un trabajo en progreso y debes revisar cuidadosamente el historial de commits para ver los cambios antes de actualizar. Para un servidor de producción, se recomienda al menos 1 TB de espacio en disco SSD, 32 GB de RAM y 8 núcleos de CPU. Para un servidor pequeño de pruebas/personal, 4 GB de RAM y 1 núcleo de CPU es suficiente.
Las traducciones se gestionan en Weblate.
Si prefieres enviar traducciones manualmente, el script update-translations.sh se puede usar para actualizar la plantilla de idioma y los archivos de traducción desde el código fuente.
Generará el archivo var/www/locale/hosting.pot que luego puedes usar como base para crear un nuevo archivo de idioma en var/www/CODIGO_DE_IDIOMA/LC_MESSAGES/hosting.po y editarlo con un programa de traducción, como Poedit.
Una vez que termines, puedes abrir un pull request, o enviarme un correo electrónico, para incluir la traducción.
La configuración fue probada con Debian 13 (Trixie) y Ubuntu 24.04 LTS. Se recomienda instalar Debian 13 o Ubuntu 24.04 en tu servidor, pero con algunos ajustes también puedes hacerlo funcionar en otras distribuciones y/o versiones. Si quieres montarlo en una raspberry pi, no uses las imágenes de raspbian ya que varias cosas se romperán. Descarga una imagen para tu modelo de pi desde https://raspi.debian.net/daily-images/.
La forma más fácil de instalar es con el instalador automatizado:
apt update && apt install git && git clone https://github.com/DanWin/hosting && cd hosting
./install.sh
El instalador maneja todo: instalación de paquetes, compilación de PHP/ImageMagick, configuración de Tor, configuración de MySQL y aprovisionamiento de servicios. Solicitará contraseñas o las generará automáticamente.
Opciones:
./install.sh --non-interactive # Omite indicaciones, genera contraseñas aleatorias
./install.sh --vanity <prefijo> # Genera una dirección .onion personalizada
./install.sh --skip-binaries # Omite la compilación (útil si ya está compilado)
./install.sh --db-pass <contraseña> # Establece la contraseña de MySQL para hosting
./install.sh --pma-pass <contraseña> # Establece la contraseña de MySQL para phpMyAdmin
./install.sh --admin-pass <contraseña> # Establece la contraseña del panel de administración
La generación de .onion personalizada usa mkp224o (compilado automáticamente). Solo son válidos los caracteres a-z y 2-7. Un prefijo de 4 caracteres lleva minutos, 5 caracteres lleva 10-30 minutos, 6+ caracteres lleva horas.
Las credenciales se guardan en /root/hosting-credentials.txt.
cd hosting
./update.sh # Actualiza el código, conserva la configuración
./update.sh --rebuild # También reconstruye PHP/ImageMagick
./update.sh --code-only # Solo actualiza archivos PHP
El script de actualización respalda tu configuración, trae el código más reciente, restaura contraseñas y la dirección onion, y reinicia los servicios. Detecta si install_binaries.sh cambió y te avisa que debes reconstruir.
Si prefieres instalar manualmente, sigue los pasos a continuación.
Desinstala los paquetes que puedan interferir con esta configuración:
DEBIAN_FRONTEND=noninteractive apt purge -y apache2* dnsmasq* eatmydata exim4* imagemagick-6-common mysql-client* mysql-server* nginx* libnginx-mod* php7* resolvconf && systemctl disable systemd-resolved.service && systemctl stop systemd-resolved.service
Si tienes problemas para resolver nombres de host después de este paso, cambia temporalmente a un servidor de nombres público como 1.1.1.1 (de CloudFlare) o 8.8.8.8 (de Google)
rm /etc/resolv.conf && echo "nameserver 1.1.1.1" > /etc/resolv.conf
Añade repositorios adicionales (solo Debian — Ubuntu tiene nginx y brotli de forma nativa):
apt update && apt install git apt-transport-tor curl lsb-release
curl -sSL https://deb.torproject.org/torproject.org/A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89.asc > /etc/apt/trusted.gpg.d/torproject.asc
curl -sSL https://packages.sury.org/nginx/apt.gpg > /etc/apt/trusted.gpg.d/sury.gpg
echo "deb tor://apow7mjfryruh65chtdydfmqfpj5btws7nbocgtaovhvezgccyjazpqd.onion/torproject.org/ `lsb_release -cs` main" >> /etc/apt/sources.list
echo "deb https://packages.sury.org/nginx/ `lsb_release -cs` main" >> /etc/apt/sources.list
apt update && apt upgrade
Instala git y clona este repositorio
apt update && apt install git && git clone https://github.com/DanWin/hosting && cd hosting
Instala los binarios personalizados optimizados
./install_binaries.sh
Ten en cuenta que Debian también tiene un archivo de paquetes de servicio onion, por lo que quizás quieras editar /etc/apt/sources.list para cargar desde allí:
deb tor://2s4yqjx5ul6okpp3f2gaunr2syex5jgbfpfvhxxbbjwnrsvbk5v3qbid.onion/debian `lsb_release -cs` main
Copia (y modifica según tus necesidades) los archivos del sitio en var/www a /var/www y los archivos de configuración en etc a /etc después de que la instalación haya finalizado. Luego reinicia algunos servicios:
systemctl daemon-reload && systemctl restart bind9.service && systemctl restart [email protected]
Reemplaza el dominio .onion predeterminado con tu dominio:
sed -i "s/dhosting4xxoydyaivckq7tsmtgi4wfs3flpeyitekkmqwu4v4r46syd.onion/`cat /var/lib/tor/hidden_service/hostname`/g" /etc/postfix/sql/alias.cf /etc/postfix/sender_login_maps /etc/postfix/main.cf /var/www/skel/www/index.hosting.html /var/www/common.php /etc/postfix/canonical /etc/postfix-clearnet/canonical /var/www/html/squirrelmail/config/config.php
Para tu dominio clearnet, debes agregarlo a relay_domains en /etc/postfix/main.cf y editar el dominio predeterminado en los siguientes archivos:
/var/www/common.php
/etc/postfix/canonical
/etc/postfix-clearnet/canonical
Esta configuración tiene dos instancias de postfix, una para recibir y enviar correo a otros servicios .onion y otra para reescribir direcciones y pasarlas a un relay de correo orientado a clearnet. Puedes querer o no crear la segunda instancia ejecutando
postmulti -e init
postmulti -I postfix-clearnet -e create
postmulti -i clearnet -e enable
postmulti -i clearnet -p start
Si creaste una instancia, descomenta la configuración relacionada con el relay clearnet en etc/postfix/main.cf y asegúrate de copiar y modificar también los archivos de configuración de etc/postfix-clearnet
Si te encuentras con el siguiente problema: postfix: fatal: chdir(/var/spool/postfix-clearnet): No such file or directory puedes simplemente copiar el chroot de la instancia predeterminada de postfix así cd /var/spool/ && cp -a postfix/ postfix-clearnet/
Después de copiar (y modificar) la configuración de postfix, necesitas crear bases de datos a partir de los archivos de mapeo (también cada vez que actualices esos archivos):
postalias /etc/aliases
postmap /etc/postfix/canonical /etc/postfix/sender_login_maps /etc/postfix/transport
postmap /etc/postfix-clearnet/canonical /etc/postfix-clearnet/sasl_password /etc/postfix-clearnet/transport #solo si tienes una segunda instancia
Para guardar archivos temporales en memoria, agrega lo siguiente a /etc/fstab:
tmpfs /tmp tmpfs defaults,noatime 0 0
tmpfs /var/log/nginx tmpfs rw,user,noatime 0 0
Para endurecer el sistema y ocultar los pids de los usuarios no root, agrega también lo siguiente:
proc /proc proc defaults,hidepid=2 0 0
Y agrega las opciones noatime,usrjquota=aquota.user,jqfmt=vfsv1 al punto de montaje /home, luego inicializa la cuota. Reemplaza /home con /, si no tienes una partición separada:
systemctl daemon-reload
mount -o remount $(findmnt -n -o TARGET --target /home)
quotacheck -cMu $(findmnt -n -o TARGET --target /home)
quotaon $(findmnt -n -o TARGET --target /home)
En algunos casos, puedes obtener un error de que la cuota no es compatible. Esto suele ocurrir en entornos virtuales. Asegúrate de tener el kernel completo instalado, no uno con un paquete -virtual. Suelen ser linux-image-amd64, linux-image-arm64 o linux-image-generic, según tu distribución. También asegúrate de estar ejecutando una máquina virtual real (por ejemplo, KVM). Algunos proveedores venden VPS contenerizados (por ejemplo, OpenVZ), lo que significa que no ejecutas tu propio kernel...
Instala sodium_compat para soporte de hidden_service v3
cd /var/www && composer install
Crea un usuario mysql para phpmyadmin y configúralo en /var/www/html/phpmyadmin/config.inc.php y completa $cfg['blowfish_secret'] con caracteres aleatorios:
mysql
CREATE USER 'phpmyadmin'@'%' IDENTIFIED BY 'MI_CONTRASEÑA';
CREATE DATABASE phpmyadmin;
GRANT ALL PRIVILEGES ON phpmyadmin.* TO 'phpmyadmin'@'%';
FLUSH PRIVILEGES;
quit
mysql phpmyadmin < /var/www/html/phpmyadmin/sql/create_tables.sql
Crea un usuario mysql con todos los permisos para nuestra gestión de hosting:
mysql
CREATE USER 'hosting'@'%' IDENTIFIED BY 'MI_CONTRASEÑA';
GRANT ALL PRIVILEGES ON *.* TO 'hosting'@'%' WITH GRANT OPTION;
FLUSH PRIVILEGES;
quit
Luego edita la configuración de la base de datos en /var/www/common.php y /etc/postfix/sql/alias.cf
Por último, pero no menos importante, configura la base de datos ejecutando
php /var/www/setup.php
Habilita los temporizadores de systemd para ejecutar regularmente varias tareas de gestión:
systemctl enable hosting-del.timer && systemctl enable hosting.timer && systemctl enable hosting-autoscale.timer
El paso final es reiniciar, esperar unos 5 minutos para que todos los servicios se inicien, y verificar que todo funcione creando una cuenta de prueba.
Los usuarios pueden elegir entre PHP 8.2, 8.3, 8.4 y 8.5 al registrarse y cambiar su versión desde el panel de control. La versión predeterminada es PHP 8.5.
Las instancias de Tor se escalan automáticamente según la cantidad de cuentas. El hosting-autoscale.timer se ejecuta cada hora y agrega una nueva instancia por cada ~250 cuentas. Los IDs de instancia van de la a a la z, luego aa, ab, etc. También puedes configurar manualmente las instancias en SERVICE_INSTANCES en /var/www/common.php y ejecutar setup.php.
htmlspecialchars()script-src 'none'