Pure-FTPd Docker image based with MySQL, PostgreSQL and LDAP support.
Tip
Want to be notified of new releases? Check out 🔔 Diun (Docker Image Update Notifier) project!
- Features
- Build locally
- Image
- Environment variables
- Volumes
- Ports
- Usage
- Upgrade
- Notes
- Contributing
- License
- Multi-platform image
- s6-overlay as process supervisor
- PureDB, MySQL, PostgreSQL and LDAP support
- Latest Pure-FTPd release compiled from source
- Support of
argon2
andscrypt
hashing method through Libsodium - Logs processed to
stdout
through socklog-overlay - Support of
pure-uploadscript
PASSIVE_IP
for PASV support automatically resolved
git clone https://github.com/crazy-max/docker-pure-ftpd.git
cd docker-pure-ftpd
# Build image and output to docker (default)
docker buildx bake
# Build multi-platform image
docker buildx bake image-all
Registry | Image |
---|---|
Docker Hub | crazymax/pure-ftpd |
GitHub Container Registry | ghcr.io/crazy-max/pure-ftpd |
Following platforms for this image are available:
$ docker buildx imagetools inspect crazymax/pure-ftpd --format "{{json .Manifest}}" | \
jq -r '.manifests[] | select(.platform.os != null and .platform.os != "unknown") | .platform | "\(.os)/\(.architecture)\(if .variant then "/" + .variant else "" end)"'
linux/386
linux/amd64
linux/arm/v6
linux/arm/v7
linux/arm64
linux/ppc64le
TZ
: Timezone assigned to the container (defaultUTC
)AUTH_METHOD
: Authentication method to use. Can bepuredb
,mysql
,pgsql
orldap
(defaultpuredb
)SECURE_MODE
: Enable secure mode (defaulttrue
)PASSIVE_IP
: IP/Host for PASV support (default auto resolved withdig +short myip.opendns.com @resolver1.opendns.com
)PASSIVE_PORT_RANGE
: Port range for passive connections (default30000:30009
)DB_TIMEOUT
: Time in seconds after which we stop trying to reach the database server. Only used formysql
andpgsql
auth method (default45
)UPLOADSCRIPT
: What program/script to run after an upload. It has to be an absolute filename. (for example/data/uploadscript.sh
)
⚠️ Do not set--uploadscript
flag. It will be added ifUPLOADSCRIPT
is defined.
/data
: Contains config files and PureDB file
2100
: FTP port30000-30009
: PASV port range
Docker compose is the recommended way to run this image. You can use the following compose template, then run the container:
docker compose up -d
docker compose logs -f
You can also use the following minimal command:
$ docker run -d --name pure-ftpd \
-p 2100:2100 \
-p 30000-30009:30000-30009 \
-e "TZ=Europe/Paris" \
-v $(pwd)/data:/data \
crazymax/pure-ftpd
Recreate the container whenever I push an update:
docker compose pull
docker compose up -d
This image uses flags instead of the configuration file to set Pure-FTPd. Some
flags are forced
but you can pass additional flags in /data/pureftpd.flags
file:
-d
-d
--maxclientsperip 5
--minuid 100
--limitrecursion 10000:3
SECURE_MODE
enables
specially crafted flags
to enforced security of Pure-FTPd.
Using PureDB authentication method, the container will create a blank password file in
/data/pureftpd.passwd
and a initialize a PureDB database in /data/pureftpd.pdb
. If a password file is
already available, it will be read on startup and the PureDB database will be updated.
At first execution of the container no user will be available and you will have to create one:
$ docker compose exec pureftpd pure-pw useradd foo -u 1003 -g 1005 -d /home/foo -m
Password:
Enter it again:
$ docker compose exec pureftpd pure-pw list
foo /home/foo/./
$ cat ./data/pureftpd.passwd
foo:$2a$10$Oqn7I2P7YaGxQrtuydcDKuxmCJqPR7a79EeDy2gChyOGEnYA4UIPK:1003:1005::/home/foo/./::::::::::::
User
foo
will be created with uid1003
, gid1005
with his home directory located at/home/foo
. The password will be asked after. More info about local users database: https://github.com/jedisct1/pure-ftpd/blob/master/README.Virtual-Users
Looking at the previous example, don't forget to persist the home directory through a named or bind mounted volume like:
version: "3.2"
services:
pureftpd:
image: crazymax/pure-ftpd
container_name: pureftpd
ports:
- "2100:2100"
- "30000-30009:30000-30009"
volumes:
- "./data:/data"
- "./foo:/home/foo"
environment:
- "TZ=Europe/Paris"
- "AUTH_METHOD=puredb"
restart: always
A quick example to use MySQL authentication method is also available using a MariaDB container.
Before using starting the container, a MySQL configuration file must
be available in /data/pureftpd-mysql.conf
.
In the docker compose example available, the database and the users table will be created at first launch.
To create your first user you can use this one line command:
$ docker compose exec db mysql -u pureftpd -p'asupersecretpassword' -e "INSERT INTO users (User,Password,Uid,Gid,Dir) VALUES ('foo',ENCRYPT('test'),'1003','1005','/home/foo');" pureftpd
$ docker compose exec db mysql -u pureftpd -p'asupersecretpassword' -e "SELECT * FROM users;" pureftpd
+------+---------------+------+------+-----------+
| User | Password | Uid | Gid | Dir |
+------+---------------+------+------+-----------+
| foo | Oo4cJdd1HNVA6 | 1003 | 1005 | /home/foo |
+------+---------------+------+------+-----------+
User
foo
will be created with uid1003
, gid1005
with his home directory located at/home/foo
. Here we assumecrypt
is theMySQLCrypt
method and the passwordtest
is hashed using crypt. More info about MySQL authentication method: https://github.com/jedisct1/pure-ftpd/blob/master/README.MySQL
Like MySQL, there is also a quick example to use PostgreSQL authentication method using a
PostgreSQL container. And also before starting the container, a
PostgreSQL configuration file must be available
in /data/pureftpd-pgsql.conf
.
In the docker compose example available, the database and the users table will be also created at first launch.
How add new user with encrypted password?
CREATE EXTENSION pgcrypto;
INSERT INTO "users" ("User", "Password", "Dir") VALUES ('foo', crypt('mypassword', gen_salt('bf')), '/home/foo');
More info about PostgreSQL authentication method: https://github.com/jedisct1/pure-ftpd/blob/master/README.PGSQL
TLS connections require certificates, as well as their
key. Both can be bundled into a single file. If you have both a .pem
file and a .key
file, just concatenate the
content of the .key
file to the .pem
file.
The certificate needs to be located in /data/pureftpd.pem
and --tls <opt>
added to enable TLS connection.
To get started, you can create a self-signed certificate with the following command:
docker run --rm -it --entrypoint '' -v $(pwd)/data:/data crazymax/pure-ftpd \
openssl dhparam -out /data/pureftpd-dhparams.pem 2048
docker run --rm -it --entrypoint '' -v $(pwd)/data:/data crazymax/pure-ftpd \
openssl req -x509 -nodes -newkey rsa:2048 -sha256 -keyout /data/pureftpd.pem -out /data/pureftpd.pem
Logs are displayed through stdout
using socklog-overlay
. You can increase verbosity with -d -d
flags.
$ docker compose logs -f pureftpd
Attaching to pureftpd
pureftpd | [s6-init] making user provided files available at /var/run/s6/etc...exited 0.
pureftpd | [s6-init] ensuring user provided files have correct perms...exited 0.
pureftpd | [fix-attrs.d] applying ownership & permissions fixes...
pureftpd | [fix-attrs.d] done.
pureftpd | [cont-init.d] executing container initialization scripts...
pureftpd | [cont-init.d] 01-config.sh: executing...
pureftpd | Setting timezone to America/Edmonton...
pureftpd | Use PureDB authentication method
pureftpd | Flags
pureftpd | Secure:
pureftpd | Additional:
pureftpd | All: --bind 0.0.0.0,2100 --ipv4only --passiveportrange 30000:30009 --noanonymous --createhomedir --nochmod --syslogfacility ftp --forcepassiveip 90.101.64.158 --login puredb:/data/pureftpd.pdb
pureftpd | [cont-init.d] 01-config.sh: exited 0.
pureftpd | [cont-init.d] 02-service.sh: executing...
pureftpd | [cont-init.d] 02-service.sh: exited 0.
pureftpd | [cont-init.d] 03-uploadscript.sh: executing...
pureftpd | [cont-init.d] 03-uploadscript.sh: exited 0.
pureftpd | [cont-init.d] ~-socklog: executing...
pureftpd | [cont-init.d] ~-socklog: exited 0.
pureftpd | [cont-init.d] done.
pureftpd | [services.d] starting services
pureftpd | [services.d] done.
pureftpd | ftp.info: May 21 18:09:56 pure-ftpd: (?@192.168.0.1) [INFO] New connection from 192.168.0.1
pureftpd | ftp.info: May 21 18:09:56 pure-ftpd: (?@192.168.0.1) [INFO] foo is now logged in
pureftpd | ftp.notice: May 21 18:10:17 pure-ftpd: (foo@192.168.0.1) [NOTICE] /home/foo//unlock.bin uploaded (1024 bytes, 448.83KB/sec)
...
Want to contribute? Awesome! The most basic way to show your support is to star the project, or to raise issues. You can also support this project by becoming a sponsor on GitHub or by making a PayPal donation to ensure this journey continues indefinitely!
Thanks again for your support, it is much appreciated! 🙏
MIT. See LICENSE
for more details.