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-release
yum -y install yum-priorities

Edita /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 update

Ahora podemos instalar el servidor web Apache, PHP, MariaDB y phpMyAdmin de la siguiente manera:

yum -y install mariadb mariadb-server phpmyadmin httpd php

Ahora configuramos phpMyAdmin. Cambiamos la configuración de Apache para que phpMyAdmin permita conexiones no solo desde localhost (comentando todo en la sección y añadiendo la línea Require all granted):

nano /etc/httpd/conf.d/phpMyAdmin.conf

para 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 --reload

Luego inicia MariaDB y Apache.

systemctl enable mariadb.service  
systemctl start mariadb.service
systemctl enable httpd.service  
systemctl start httpd.service

Crea 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-ftpd

Luego 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 ftpuser

El servicio ftp debe ser permitido por el firewall-cmd de la siguiente manera:

firewall-cmd --permanent --zone=public --add-service=ftp  
firewall-cmd --reload

4 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 -p
CREATE 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.conf
MYSQLSocket      /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.service

6 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 -p
USE 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.

Conectar al servidor FTP con FileZilla.

Si puedes conectarte, ¡felicitaciones! Si no, algo salió mal.

Ahora, si ejecutas

ls -l /home

debes 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.

El Panel de Control de PHPMyAdmin

La base de datos MySQL de pure-ftpd

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:
    Agregar un usuario FTP.
  • 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 /home

Luego 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.service

9 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

Share: X/Twitter LinkedIn

Recibe nuevas publicaciones en tu bandeja de entrada.

No spam. Cancela la suscripción en cualquier momento.