Servidor FTP · 14 min read · Dec 24, 2025
Alojamiento Virtual Con PureFTPd Y MySQL (Incl. Gestión De Cuotas Y Ancho De Banda) En CentOS 7.0
Este documento describe cómo instalar un servidor PureFTPd que utiliza usuarios virtuales de una base de datos MySQL en lugar de usuarios reales del sistema. Esto es mucho más eficiente y permite tener miles de usuarios FTP en una sola máquina. Además de eso, mostraré el uso de cuotas y límites de ancho de banda de carga/descarga con esta configuración. Las contraseñas se almacenarán encriptadas como cadenas MD5 en la base de datos.
Para la administración de la base de datos MySQL, puedes utilizar herramientas basadas en la web como phpMyAdmin, que también se instalará en este tutorial. phpMyAdmin es una interfaz gráfica cómoda, lo que significa que no tienes que lidiar con la línea de comandos.
Este tutorial se basa en CentOS 7.0. Ya deberías haber configurado un sistema CentOS 7 básico y mínimo.
Este tutorial está destinado como una guía práctica; no cubre los antecedentes teóricos. Estos se tratan en muchos otros documentos en la web.
¡Este documento se proporciona sin garantía de ningún tipo! Quiero decir que este no es el único modo de configurar un sistema así. Hay muchas maneras de lograr este objetivo, pero este es el camino que elijo.
1 Nota Preliminar
En este tutorial, utilizo el nombre de host server1.example.com con la dirección IP 192.168.0.100. Estas configuraciones pueden diferir para ti, así que debes reemplazarlas donde sea apropiado.
2 Instalar MySQL Y phpMyAdmin
Primero, habilitamos el repositorio EPEL en nuestro sistema CentOS, ya que algunos paquetes que vamos a instalar en el transcurso de este tutorial no están disponibles en los repositorios oficiales de CentOS 7.0:
rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY*Luego habilitamos el repositorio EPEL en nuestro sistema CentOS, ya que muchos de los paquetes que vamos a instalar en el transcurso de este tutorial no están disponibles en el repositorio oficial de CentOS 7:
yum -y install epel-releaseyum -y install yum-prioritiesEdita /etc/yum.repos.d/epel.repo…
nano /etc/yum.repos.d/epel.repo… y agrega la línea priority=10 a la sección [epel]:
[epel]
name=Paquetes Extra para Linux Empresarial 7 - $basearch
#baseurl=http://download.fedoraproject.org/pub/epel/7/$basearch
mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=epel-7&arch=$basearch
failovermethod=priority
enabled=1
priority=10
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7
[...]Luego actualizamos nuestros paquetes existentes en el sistema:
yum updateAhora podemos instalar MySQL y phpMyAdmin de la siguiente manera:
yum install mariadb mariadb-server phpmyadmin httpd phpAhora configuramos phpMyAdmin. Cambiamos la configuración de Apache para que phpMyAdmin permita conexiones no solo desde localhost (comentando todo en la sección
vi /etc/httpd/conf.d/phpMyAdmin.confpara que el archivo se vea así:
# phpMyAdmin - Navegador MySQL basado en web escrito en php
#
# Solo permite localhost por defecto
#
# Pero permitir phpMyAdmin a cualquier persona que no sea localhost debe considerarse
# peligroso a menos que esté debidamente asegurado por SSL
Alias /phpMyAdmin /usr/share/phpMyAdmin
Alias /phpmyadmin /usr/share/phpMyAdmin
#
# # Apache 2.4
#
# Require ip 127.0.0.1
# Require ip ::1
#
#
#
# # Apache 2.2
# Order Deny,Allow
# # Deny from All
# Allow from 127.0.0.1
Options Indexes
AllowOverride None
Require all granted
# Allow from ::1
#
# Apache 2.4
Require ip 127.0.0.1
Require ip ::1
# Apache 2.2
Order Deny,Allow
Deny from All
Allow from 127.0.0.1
Allow from ::1
# Estos directorios no requieren acceso a través de HTTP - tomados del tarball original de
# phpMyAdmin
#
Order Deny,Allow
Deny from All
Allow from None
Order Deny,Allow
Deny from All
Allow from None
Order Deny,Allow
Deny from All
Allow from None
# Esta configuración previene que mod_security en los directorios de phpMyAdmin
# filtre SQL, etc. Esto puede romper tu implementación de mod_security.
#
#
#
# SecRuleInheritance Off
#
#
Luego creamos los enlaces de inicio del sistema para MySQL y Apache (para que ambos se inicien automáticamente cada vez que se inicie el sistema) y comenzamos ambos servicios. Además, ambos servicios deben ser permitidos por el firewall:
firebase-cmd --permanent --zone=public --add-service=http
firebase-cmd --permanent --zone=public --add-service=https
firebase-cmd --reloadsystemctl enable mariadb.service
systemctl start mariadb.servicesystemctl enable httpd.service
systemctl start httpd.serviceCrea una contraseña para el usuario root de MySQL (reemplaza yourmariadbpassword con la contraseña que deseas usar):
mysql_secure_installation[root@server1 ~]# mysql_secure_installation
/usr/bin/mysql_secure_installation: línea 379: find_mysql_client: comando no encontrado
NOTA: ¡SE RECOMIENDA EJECUTAR TODAS LAS PARTES DE ESTE SCRIPT PARA TODOS LOS SERVIDORES MariaDB EN USO DE PRODUCCIÓN! ¡LEA CADA PASO CUIDADOSAMENTE!
Para iniciar sesión en MariaDB y asegurarla, necesitaremos la contraseña actual para el usuario root. Si acabas de instalar MariaDB y no has establecido la contraseña de root aún, la contraseña estará en blanco, así que solo debes presionar enter aquí. <–ENTER
Ingresa la contraseña actual para root (presiona enter si no hay): <–ENTER
OK, se utilizó la contraseña correctamente, continuando…
Establecer la contraseña de root asegura que nadie pueda iniciar sesión en el usuario root de MariaDB sin la autorización adecuada.
¿Establecer contraseña de root? [Y/n] <–ENTER
Nueva contraseña: <–yourmariadbpassword
Reingresa nueva contraseña: <–yourmariadbpassword
¡Contraseña actualizada con éxito!
Recargando tablas de privilegios..
… ¡Éxito!
Por defecto, una instalación de MariaDB tiene un usuario anónimo, permitiendo que cualquiera inicie sesión en MariaDB sin tener que tener una cuenta de usuario creada para ellos. Esto está destinado solo para pruebas, y para hacer que la instalación sea un poco más fluida. Debes eliminarlos antes de pasar a un entorno de producción.
¿Eliminar usuarios anónimos? [Y/n] <–ENTER
… ¡Éxito!
Normalmente, solo se debería permitir que root se conecte desde ‘localhost’. Esto asegura que alguien no pueda adivinar la contraseña de root desde la red.
¿Deshabilitar inicio de sesión remoto para root? [Y/n] <–ENTER
… ¡Éxito!
Por defecto, MariaDB viene con una base de datos llamada ‘test’ a la que cualquiera puede acceder. Esto también está destinado solo para pruebas, y debe ser eliminado antes de pasar a un entorno de producción.
¿Eliminar base de datos de prueba y acceso a ella? [Y/n] <–ENTER
- Eliminando base de datos de prueba…
… ¡Éxito! - Eliminando privilegios sobre la base de datos de prueba…
… ¡Éxito!
Recargar las tablas de privilegios asegurará que todos los cambios realizados hasta ahora tengan efecto inmediato.
¿Recargar tablas de privilegios ahora? [Y/n] <–ENTER
… ¡Éxito!
Limpiando…
¡Todo listo! Si has completado todos los pasos anteriores, tu instalación de MariaDB debería estar ahora segura.
¡Gracias por usar MariaDB!
[root@server1 ~]#
3 Instalar PureFTPd Con Soporte Para MySQL
El paquete PureFTPd de CentOS soporta varios backends, como MySQL, PostgreSQL, LDAP, etc. Por lo tanto, todo lo que tenemos que hacer es instalar el paquete normal de PureFTPd:
yum install pure-ftpdLuego creamos un grupo ftp (ftpgroup) y un usuario (ftpuser) al que se mapearán todos nuestros usuarios virtuales. Reemplaza el grupo y el id de usuario 2001 con un número que esté libre en tu sistema:
groupadd -g 2001 ftpgroup
useradd -u 2001 -s /bin/false -d /bin/null -c "usuario pureftpd" -g ftpgroup ftpuserEl servicio ftp debe ser permitido por el firewall-cmd de la siguiente manera:
firebase-cmd --permanent --zone=public --add-service=ftp
firebase-cmd --reload4 Crear La Base De Datos MySQL Para PureFTPd
Ahora creamos una base de datos llamada pureftpd y un usuario MySQL llamado pureftpd que el demonio PureFTPd utilizará más adelante para conectarse a la base de datos pureftpd:
mysql -u root -pCREATE DATABASE pureftpd;
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP ON pureftpd.* TO 'pureftpd'@'localhost' IDENTIFIED BY 'ftpdpass';
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP ON pureftpd.* TO 'pureftpd'@'localhost.localdomain' IDENTIFIED BY 'ftpdpass';
FLUSH PRIVILEGES;Reemplaza la cadena ftpdpass con la contraseña que deseas usar para el usuario MySQL pureftpd. Aún en la consola de MySQL, creamos la tabla de base de datos que necesitamos (sí, ¡solo hay una tabla!):
USE pureftpd;CREATE TABLE ftpd (
User varchar(16) NOT NULL default '',
status enum('0','1') NOT NULL default '0',
Password varchar(64) NOT NULL default '',
Uid varchar(11) NOT NULL default '-1',
Gid varchar(11) NOT NULL default '-1',
Dir varchar(128) NOT NULL default '',
ULBandwidth smallint(5) NOT NULL default '0',
DLBandwidth smallint(5) NOT NULL default '0',
comment tinytext NOT NULL,
ipaccess varchar(15) NOT NULL default '*',
QuotaSize smallint(5) NOT NULL default '0',
QuotaFiles int(11) NOT NULL default 0,
PRIMARY KEY (User),
UNIQUE KEY User (User)
) ENGINE=MyISAM;quit;Como habrás notado, con el comando quit; hemos salido de la consola de MySQL y estamos de vuelta en la consola de Linux.
Por cierto, (asumo que el nombre de host de tu sistema de servidor ftp es server1.example.com) puedes acceder a phpMyAdmin en http://server1.example.com/phpMyAdmin/ (también puedes usar la dirección IP en lugar de server1.example.com) en un navegador e iniciar sesión como el usuario pureftpd. Luego puedes echar un vistazo a la base de datos. Más adelante puedes usar phpMyAdmin para administrar tu servidor PureFTPd.
5 Configurar PureFTPd
Edita /etc/pure-ftpd/pure-ftpd.conf y asegúrate de que las líneas ChrootEveryone, MySQLConfigFile y CreateHomeDir estén habilitadas y se vean así:
vi /etc/pure-ftpd/pure-ftpd.conf[...]
ChrootEveryone yes
[...]
MySQLConfigFile /etc/pure-ftpd/pureftpd-mysql.conf
[...]
CreateHomeDir yes
[...]La configuración ChrootEveryone hará que PureFTPd chroot a cada usuario virtual en su directorio de inicio, por lo que no podrá navegar por directorios y archivos fuera de su directorio de inicio. La línea CreateHomeDir hará que PureFTPd cree el directorio de inicio de un usuario cuando el usuario inicie sesión y el directorio de inicio aún no exista.
Luego editamos /etc/pure-ftpd/pureftpd-mysql.conf. Debería verse así:
cp /etc/pure-ftpd/pureftpd-mysql.conf /etc/pure-ftpd/pureftpd-mysql.conf_orig
cat /dev/null > /etc/pure-ftpd/pureftpd-mysql.conf
vi /etc/pure-ftpd/pureftpd-mysql.confMYSQLSocket /var/lib/mysql/mysql.sock
#MYSQLServer localhost
#MYSQLPort 3306
MYSQLUser pureftpd
MYSQLPassword ftpdpass
MYSQLDatabase pureftpd
#MYSQLCrypt md5, cleartext, crypt() o password() - md5 es MUY RECOMENDABLE sobre texto claro
MYSQLCrypt md5
MYSQLGetPW SELECT Password FROM ftpd WHERE User="\L" AND status="1" AND (ipaccess = "*" OR ipaccess LIKE "\R")
MYSQLGetUID SELECT Uid FROM ftpd WHERE User="\L" AND status="1" AND (ipaccess = "*" OR ipaccess LIKE "\R")
MYSQLGetGID SELECT Gid FROM ftpd WHERE User="\L"AND status="1" AND (ipaccess = "*" OR ipaccess LIKE "\R")
MYSQLGetDir SELECT Dir FROM ftpd WHERE User="\L"AND status="1" AND (ipaccess = "*" OR ipaccess LIKE "\R")
MySQLGetBandwidthUL SELECT ULBandwidth FROM ftpd WHERE User="\L"AND status="1" AND (ipaccess = "*" OR ipaccess LIKE "\R")
MySQLGetBandwidthDL SELECT DLBandwidth FROM ftpd WHERE User="\L"AND status="1" AND (ipaccess = "*" OR ipaccess LIKE "\R")
MySQLGetQTASZ SELECT QuotaSize FROM ftpd WHERE User="\L"AND status="1" AND (ipaccess = "*" OR ipaccess LIKE "\R")
MySQLGetQTAFS SELECT QuotaFiles FROM ftpd WHERE User="\L"AND status="1" AND (ipaccess = "*" OR ipaccess LIKE "\R")Asegúrate de reemplazar la cadena ftpdpass con la contraseña real para el usuario MySQL pureftpd en la línea MYSQLPassword. ¡Ten en cuenta que usamos md5 como método MYSQLCrypt, lo que significa que almacenaremos las contraseñas de los usuarios como una cadena MD5 en la base de datos, lo cual es mucho más seguro que usar contraseñas en texto plano!
Ahora creamos los enlaces de inicio del sistema para PureFTPd y lo iniciamos:
systemctl enable pure-ftpd.service
systemctl start pure-ftpd.service6 Población De La Base De Datos Y Prueba
Para poblar la base de datos, puedes usar la consola de MySQL:
mysql -u root -pUSE pureftpd;Ahora creamos el usuario exampleuser con el estado 1 (lo que significa que su cuenta ftp está activa), la contraseña secret (que se almacenará encriptada usando la función MD5 de MySQL), el UID y GID 2001 (usa el id de usuario y el id de grupo que creaste al final del paso dos), el directorio de inicio /home/www.example.com, un ancho de banda de carga y descarga de 100 KB/sec. (kilobytes por segundo), y una cuota de 50 MB:
INSERT INTO `ftpd` (`User`, `status`, `Password`, `Uid`, `Gid`, `Dir`, `ULBandwidth`, `DLBandwidth`, `comment`, `ipaccess`, `QuotaSize`, `QuotaFiles`) VALUES ('exampleuser', '1', MD5('secret'), '2001', '2001', '/home/www.example.com', '100', '100', '', '*', '50', '0');quit;Ahora abre tu programa cliente FTP en tu estación de trabajo (algo como WS_FTP o SmartFTP si estás en un sistema Windows o gFTP en un escritorio Linux) y trata de conectarte. Como nombre de host usas server1.example.com (o la dirección IP del sistema), el nombre de usuario es exampleuser y la contraseña es secret.
Si puedes conectarte, ¡felicitaciones! Si no, algo salió mal.
Ahora, si ejecutas
ls -l /homedebes ver que el directorio /home/www.example.com (el directorio de inicio de exampleuser) se ha creado automáticamente, y es propiedad de ftpuser y ftpgroup (el usuario/grupo que creamos al final del paso dos):
[root@server1 ~]# ls -l /home/
total 0
drwx------. 2 administrator administrator 59 Sep 26 10:35 administrator
drwxr-xr-x. 2 ftpuser ftpgroup 22 Sep 26 12:07 www.example.com
[root@server1 ~]#7 Administración De La Base De Datos
Para la mayoría de las personas, es más fácil si tienen un front-end gráfico para MySQL; por lo tanto, también puedes usar phpMyAdmin (en este ejemplo en http://server1.example.com/phpMyAdmin/) para administrar la base de datos pureftpd.

Siempre que quieras crear un nuevo usuario, debes crear una entrada en la tabla ftpd, así que explicaré las columnas de esta tabla aquí:
Tabla ftpd:
- User: El nombre del usuario virtual de PureFTPd (por ejemplo, exampleuser).
- status: 0 o 1. 0 significa que la cuenta está deshabilitada, el usuario no puede iniciar sesión.
- Password: La contraseña del usuario virtual. Asegúrate de usar la función MD5 de MySQL para guardar la contraseña encriptada como una cadena MD5:

- UID: El id de usuario del usuario ftp que creaste al final del paso dos (por ejemplo, 2001).
- GID: El id de grupo del grupo ftp que creaste al final del paso dos (por ejemplo, 2001).
- Dir: El directorio de inicio del usuario virtual de PureFTPd (por ejemplo, /home/www.example.com). Si no existe, se creará cuando el nuevo usuario inicie sesión por primera vez a través de FTP. El usuario virtual estará encarcelado en este directorio de inicio, es decir, no puede acceder a otros directorios fuera de su directorio de inicio.
- ULBandwidth: Ancho de banda de carga del usuario virtual en KB/sec. (kilobytes por segundo). 0 significa ilimitado.
- DLBandwidth: Ancho de banda de descarga del usuario virtual en KB/sec. (kilobytes por segundo). 0 significa ilimitado.
- comment: Puedes ingresar cualquier comentario aquí (por ejemplo, para tu administración interna). Normalmente dejas este campo vacío.
- ipaccess: Ingresa aquí las direcciones IP que están permitidas para conectarse a esta cuenta FTP. * significa que cualquier dirección IP está permitida para conectarse.
- QuotaSize: Espacio de almacenamiento en MB (no KB, como en ULBandwidth y DLBandwidth) que el usuario virtual puede usar en el servidor FTP. 0 significa ilimitado.
- QuotaFiles: cantidad de archivos que el usuario virtual puede guardar en el servidor FTP. 0 significa ilimitado.
8 FTP Anónimo
Si deseas crear una cuenta ftp anónima (una cuenta ftp a la que todos pueden iniciar sesión sin una contraseña), necesitas un usuario y un grupo llamados ftp. Ambos se han creado automáticamente cuando instalaste el paquete pure-ftpd, así que no necesitas crearlos manualmente. Sin embargo, el directorio home de ftp es /var/ftp por defecto, pero me gustaría crear el directorio ftp anónimo en /home/ftp (los directorios ftp de los usuarios normales también están en /home, por ejemplo, /home/www.example.com). Pero, por supuesto, puedes usar el directorio /var/ftp para ftp anónimo, si lo prefieres.
Si deseas usar /home/ftp, abre /etc/passwd y cambia el directorio home del usuario ftp de /var/ftp a /home/ftp (no hagas esto si deseas usar /var/ftp):
vi /etc/passwd[...]
#ftp:x:14:50:Usuario FTP:/var/ftp:/sbin/nologin
ftp:x:14:50:Usuario FTP:/home/ftp:/sbin/nologin
[...]Luego mueve /var/ftp a /home (no hagas esto si deseas usar /var/ftp):
mv /var/ftp /homeLuego creamos el directorio /home/ftp/incoming que permitirá a los usuarios anónimos cargar archivos. Daremos al directorio /home/ftp/incoming permisos de 311 para que los usuarios puedan cargar, pero no ver ni descargar ningún archivo en ese directorio. El directorio /home/ftp tendrá permisos de 555 que permiten ver y descargar archivos:
chown ftp:nobody /home/ftp
cd /home/ftp
mkdir incoming
chown ftp:nobody incoming/
chmod 311 incoming/
cd ../
chmod 555 ftp/(Si deseas usar /var/ftp en su lugar, reemplaza /home/ftp con /var/ftp en los comandos anteriores.)
Los usuarios anónimos podrán iniciar sesión y se les permitirá descargar archivos de /home/ftp, pero las cargas estarán limitadas a /home/ftp/incoming (y una vez que se carga un archivo en /home/ftp/incoming, no se puede leer ni descargar desde allí; el administrador del servidor tiene que moverlo a /home/ftp primero para hacerlo disponible para otros).
Ahora tenemos que configurar PureFTPd para ftp anónimo. Abre /etc/pure-ftpd/pure-ftpd.conf y asegúrate de que tienes las siguientes configuraciones en él:
vi /etc/pure-ftpd/pure-ftpd.conf[...]
NoAnonymous no
[...]
AntiWarez no
[...]
AnonymousBandwidth 8
[...]
AnonymousCantUpload no
[...](La configuración AnonymousBandwidth es opcional: te permite limitar los anchos de banda de carga y descarga para los usuarios anónimos. 8 significa 8 KB/sec. Usa cualquier valor que desees, o comenta la línea si no deseas limitar los anchos de banda.)
Finalmente, reiniciamos PureFTPd:
systemctl restart pure-ftpd.service9 Enlaces
- PureFTPd: http://www.pureftpd.org/
- MySQL: http://www.mysql.com/
- phpMyAdmin: http://www.phpmyadmin.net/
- CentOS: http://centos.org/
Recibe nuevas publicaciones en tu bandeja de entrada.
No spam. Cancela la suscripción en cualquier momento.