Caution
We created this image for a specific use case. We're not actively pursuing to expand features in this project. We just had a legacy integration to deal with on a customer project, so we created this image in case others might find it useful.
This Docker image provides a customizable ProFTPD server with MySQL authentication support and TLS encryption.
Docker Image | Size |
---|---|
serversideup/proftpd |
The image is based on ubuntu:24.04
, providing a stable and up-to-date environment for running ProFTPD.
- ProFTPD server with MySQL authentication
- TLS encryption support
- Customizable configuration via environment variables
- Self-signed SSL certificate generation
- IP address banning (bans IP addresses for 1 hour that fail authentication 5 times in 10 minutes)
The following environment variables can be used to customize the ProFTPD server:
Variable | Description | Default Value |
---|---|---|
FTP_DEBUG_LEVEL |
Sets the debug level for ProFTPD | 0 |
FTP_LOG_LEVEL |
Sets the syslog level for ProFTPD | warn |
FTP_MASQUERADE_ADDRESS |
IP address or hostname for passive mode connections | - |
FTP_PASSIVE_PORT_RANGE_START |
Start of the passive port range | 60000 |
FTP_PASSIVE_PORT_RANGE_END |
End of the passive port range | 60100 |
FTP_SQL_USERS_TABLE |
MySQL table to authenticate users against | ftpusers |
FTP_TLS_CERTIFICATE_FILE |
SSL certificate file | /etc/ssl/ftp/proftpd.crt |
FTP_TLS_CERTIFICATE_KEY_FILE |
SSL certificate key file | /etc/ssl/ftp/proftpd.key |
FTP_TLS_REQUIRED |
Require TLS | off |
MYSQL_DATABASE |
MySQL database name | ftpdb |
MYSQL_HOST |
MySQL host | mysql |
MYSQL_PASSWORD |
MySQL password | ftppassword |
MYSQL_PORT |
MySQL port | 3306 |
MYSQL_USER |
MySQL user | ftpuser |
The following build arguments are used during the image build process:
Build Argument | Description | Value |
---|---|---|
FTP_USER |
The user under which ProFTPD will run | proftpd_user |
FTP_GROUP |
The group under which ProFTPD will run | nogroup |
FTP_SSL_CERTS_DIR |
Directory for SSL certificates | /etc/ssl/ftp |
FTP_USERS_DIR |
Base directory for user homes | /var/ftp/users |
- Build the Docker image:
docker build -t proftpd-mysql .
- Run the container:
services:
proftpd:
image: serversideup/proftpd
ports:
- "21:21"
- "990:990"
- "60000-60100:60000-60100"
environment:
- MYSQL_HOST=your_mysql_host
- MYSQL_DATABASE=your_database
- MYSQL_USER=your_user
- MYSQL_PASSWORD=your_password
- FTP_MASQUERADE_ADDRESS=your_masquerade_address
Make sure to replace the MySQL connection details with your own.
The ProFTPD configuration file (proftpd.conf
) is included in the image. It sets up the following:
- FTP and FTPS (TLS) support
- MySQL authentication
- Passive port range: 60000-60100
- TLS Protocol: TLSv1.2 and TLSv1.3
- Logging configuration
- Home directory creation for users
- Anonymous access disabled
- IP address banning (bans IP addresses for 1 hour that fail authentication 5 times in 10 minutes)
You can modify the
proftpd.conf
file to further customize the ProFTPD server according to your needs.
- The image generates a self-signed SSL certificate for FTPS. For production use, replace it with a valid SSL certificate.
- Ensure to use strong passwords for MySQL authentication.
- Review and adjust the
proftpd.conf
file to match your security requirements. - Consider using Docker secrets or a secure method to pass sensitive information like database credentials.
The following ports are exposed:
Port | Service |
---|---|
21 | FTP |
990 | FTPS (FTP over TLS) |
60000-60100 | Passive port range |
If you are using an orchestrator like Kubernetes, you will need to ensure that the ports are opened on the container and the host.
For example, for Docker Swarm you need to use the long format for the ports
directive in your docker compose file:
services:
ftp:
image: serversideup/proftpd
ports:
- target: 21
published: 21
protocol: tcp
mode: host
- target: 990
published: 990
protocol: tcp
mode: host
- target: 60000
published: 60000
protocol: tcp
mode: host
- target: 60001
published: 60001
protocol: tcp
mode: host
- target: 60002
published: 60002
protocol: tcp
mode: host
Unfortunately, Docker Swarm does not support specifying ranges for published ports with the long format, so you need to specify each port individually. Just be sure to open all ports within the range that you define within the FTP_PASSIVE_PORT_RANGE_START
and FTP_PASSIVE_PORT_RANGE_END
environment variables.
You can use either MySQL or MariaDB. Create a table in the database with the following SQL:
CREATE TABLE ftpusers (
id INT AUTO_INCREMENT PRIMARY KEY, -- Auto-incrementing primary key
username VARCHAR(255) NOT NULL, -- Username, max length 255 characters
password VARCHAR(255) NOT NULL, -- Password, max length 255 characters
uid INT NOT NULL, -- User ID, integer type
gid INT NOT NULL, -- Group ID, integer type
homedir VARCHAR(255) NOT NULL, -- Home directory path, max length 255 characters
shell VARCHAR(255) NOT NULL -- Shell, max length 255 characters
);
Then you can add users to the database with the following SQL:
INSERT INTO ftpusers (username, password, uid, gid, homedir, shell)
VALUES (
'testuser',
CONCAT('{sha256}', TO_BASE64(UNHEX(SHA2('mypassword', 256)))),
2001,
2001,
'/var/ftp/users/testuser',
'/bin/false'
);
- Discord for friendly support from the community and the team.
- GitHub for source code, bug reports, and project management.
- Get Professional Help - Get video + screen-sharing help directly from the core contributors.
As an open-source project, we strive for transparency and collaboration in our development process. We greatly appreciate any contributions members of our community can provide. Whether you're fixing bugs, proposing features, improving documentation, or spreading awareness - your involvement strengthens the project.
- Bug Report: If you're experiencing an issue while using these images, please create an issue.
- Security Report: Report critical security issues via our responsible disclosure policy.
Need help getting started? Join our Discord community and we'll help you out!
All of our software is free an open to the world. None of this can be brought to you without the financial backing of our sponsors.
No bronze sponsors yet. Become a sponsor →We're Dan and Jay - a two person team with a passion for open source products. We created Server Side Up to help share what we learn.
- 📖 Blog - Get the latest guides and free courses on all things web/mobile development.
- 🙋 Community - Get friendly help from our community members.
- 🤵♂️ Get Professional Help - Get video + screen-sharing support from the core contributors.
- 💻 GitHub - Check out our other open source projects.
- 📫 Newsletter - Skip the algorithms and get quality content right to your inbox.
- 🐥 Twitter - You can also follow Dan and Jay.
- ❤️ Sponsor Us - Please consider sponsoring us so we can create more helpful resources.
If you appreciate this project, be sure to check out our other projects.
- The Ultimate Guide to Building APIs & SPAs: Build web & mobile apps from the same codebase.
- Building Multi-Platform Browser Extensions: Ship extensions to all browsers from the same codebase.
- Bugflow: Get visual bug reports directly in GitHub, GitLab, and more.
- SelfHost Pro: Connect Stripe or Lemonsqueezy to a private docker registry for self-hosted apps.
- AmplitudeJS: Open-source HTML5 & JavaScript Web Audio Library.
- Spin: Laravel Sail alternative for running Docker from development → production.
- Financial Freedom: Open source alternative to Mint, YNAB, & Monarch Money.