Servidor FTP · 14 min read · Dec 24, 2025
Servidor FTP con PureFTPd, MariaDB y Usuarios Virtuales (incl. Gestión de Cuotas y Ancho de Banda) en CentOS 7.2
Este documento describe cómo instalar un servidor PureFTPd que utiliza usuarios virtuales de una base de datos MariaDB (compatible con 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, 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 MariaDB, puedes usar 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.2. Ya deberías haber configurado un sistema CentOS 7.2 básico y mínimo.
Este tutorial está destinado a ser 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 esta no es la única forma 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.1.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.2:
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 añade la línea priority=10 a la sección [epel]:
[epel]
name=Paquetes Extra para Enterprise Linux 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 el servidor web Apache, PHP, MariaDB y phpMyAdmin de la siguiente manera:
yum -y 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
nano /etc/httpd/conf.d/phpMyAdmin.confpara que el archivo se vea así:
# phpMyAdmin - Navegador MySQL basado en web escrito en php
#
# Permite solo localhost por defecto
#
# Pero permitir phpMyAdmin a cualquiera que no sea localhost debería considerarse
# peligroso a menos que esté debidamente asegurado por SSL
Alias /phpMyAdmin /usr/share/phpMyAdmin
Alias /phpmyadmin /usr/share/phpMyAdmin
AddDefaultCharset UTF-8
#
# # 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
# phpMyAdmin upstream
#
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.
Abre los puertos http y https cuando el Firewall de CentOS “firewalld” esté instalado en tu servidor.
firewall-cmd --permanent --zone=public --add-service=http
firewall-cmd --permanent --zone=public --add-service=https
firewall-cmd --reloadLuego inicia MariaDB y Apache.
systemctl 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 EN 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
Introduce 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 la 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 crear una cuenta de usuario 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, se debería permitir que root solo se conecte desde ‘localhost’. Esto asegura que alguien no pueda adivinar la contraseña de root desde la red.
¿Deshabilitar el inicio de sesión remoto de 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 eliminarse antes de pasar a un entorno de producción.
¿Eliminar la base de datos de prueba y el acceso a ella? [Y/n] <–ENTER
- Eliminando base de datos de prueba…
… ¡Éxito! - Eliminando privilegios en la base de datos de prueba…
… ¡Éxito!
Recargar las tablas de privilegios asegurará que todos los cambios realizados hasta ahora surtan efecto de 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 / MariaDB
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 -y 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:
firewall-cmd --permanent --zone=public --add-service=ftp
firewall-cmd --reload4 Crear la Base de Datos para PureFTPd
Ahora creamos una base de datos llamada pureftpd y un usuario de MariaDB llamado pureftpd que el demonio PureFTPd usará más tarde 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í:
nano /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 personal, por lo que no podrá navegar por directorios y archivos fuera de su directorio personal. La línea CreateHomeDir hará que PureFTPd cree el directorio personal de un usuario cuando el usuario inicie sesión y el directorio personal 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
nano /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 claro!
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 del Servidor
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 grupo que creaste al final del paso dos), el directorio personal /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 FileZilla 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 personal 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 Jun 21 16:13 administrator
drwxr-xr-x. 2 ftpuser ftpgroup 22 Jul 4 18:30 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 una interfaz gráfica para MySQL; por lo tanto, también puedes usar phpMyAdmin (en este ejemplo bajo 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 personal 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á encerrado en este directorio personal, es decir, no puede acceder a otros directorios fuera de su directorio personal.
- 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 personal 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 personal del usuario ftp de /var/ftp a /home/ftp (no hagas esto si deseas usar /var/ftp):
nano /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 un archivo se cargue en /home/ftp/incoming, no se puede leer ni descargar desde allí; el administrador del servidor debe 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 tengas las siguientes configuraciones en él:
nano /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 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 Descarga este servidor CentOS 7.2 como máquina virtual
Esta configuración está disponible como descarga de máquina virtual en formato ova/ovf (compatible con VMWare y Virtualbox) para suscriptores de howtoforge.
Detalles de inicio de sesión para la VM
- La contraseña de root es: howtoforge
- La contraseña del usuario “administrator” es: howtoforge
Por favor, cambia ambas contraseñas en el primer inicio de sesión.
- La dirección IP de la VM es 192.168.1.100
10 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.