diff --git a/FluentFTP.Dockers/pureftpd/.travis.yml b/FluentFTP.Dockers/pureftpd/.travis.yml deleted file mode 100644 index 056f13a44..000000000 --- a/FluentFTP.Dockers/pureftpd/.travis.yml +++ /dev/null @@ -1,14 +0,0 @@ -sudo: required - -services: - - docker - -before_install: - - make build - - make run-tls - - make logs-for-5 - - docker ps -a # check it's running - - sudo apt-get install lftp # to make a test ftp connection - -script: - - make test-bob-tls # diff --git a/FluentFTP.Dockers/pureftpd/Dockerfile b/FluentFTP.Dockers/pureftpd/Dockerfile index 4481573b3..dc18f142e 100644 --- a/FluentFTP.Dockers/pureftpd/Dockerfile +++ b/FluentFTP.Dockers/pureftpd/Dockerfile @@ -1,97 +1,77 @@ -#Stage 1 : builder debian image -FROM debian:buster as builder - -# properly setup debian sources -ENV DEBIAN_FRONTEND noninteractive -RUN echo "deb http://http.debian.net/debian buster main\n\ -deb-src http://http.debian.net/debian buster main\n\ -deb http://http.debian.net/debian buster-updates main\n\ -deb-src http://http.debian.net/debian buster-updates main\n\ -deb http://security.debian.org buster/updates main\n\ -deb-src http://security.debian.org buster/updates main\n\ -" > /etc/apt/sources.list - -# install package building helpers -# rsyslog for logging (ref https://github.com/stilliard/docker-pure-ftpd/issues/17) -RUN apt-get -y update && \ - apt-get -y --force-yes --fix-missing install dpkg-dev debhelper &&\ - apt-get -y build-dep pure-ftpd - - -# Build from source - we need to remove the need for CAP_SYS_NICE and CAP_DAC_READ_SEARCH -RUN mkdir /tmp/pure-ftpd/ && \ - cd /tmp/pure-ftpd/ && \ - apt-get source pure-ftpd && \ - cd pure-ftpd-* && \ - ./configure --with-tls | grep -v '^checking' | grep -v ': Entering directory' | grep -v ': Leaving directory' && \ - sed -i '/CAP_SYS_NICE,/d; /CAP_DAC_READ_SEARCH/d; s/CAP_SYS_CHROOT,/CAP_SYS_CHROOT/;' src/caps_p.h && \ - dpkg-buildpackage -b -uc | grep -v '^checking' | grep -v ': Entering directory' | grep -v ': Leaving directory' - - -#Stage 2 : actual pure-ftpd image -FROM debian:buster-slim - -# feel free to change this ;) -LABEL maintainer "Andrew Stilliard " - -# install dependencies -# FIXME : libcap2 is not a dependency anymore. .deb could be fixed to avoid asking this dependency -ENV DEBIAN_FRONTEND noninteractive -RUN apt-get -y update && \ - apt-get --no-install-recommends --yes install \ - libc6 \ - libcap2 \ - libmariadb3 \ - libpam0g \ - libssl1.1 \ - lsb-base \ - openbsd-inetd \ - openssl \ - perl \ - rsyslog - -COPY --from=builder /tmp/pure-ftpd/*.deb /tmp/pure-ftpd/ - -# install the new deb files -RUN dpkg -i /tmp/pure-ftpd/pure-ftpd-common*.deb &&\ - dpkg -i /tmp/pure-ftpd/pure-ftpd_*.deb && \ - # dpkg -i /tmp/pure-ftpd/pure-ftpd-ldap_*.deb && \ - # dpkg -i /tmp/pure-ftpd/pure-ftpd-mysql_*.deb && \ - # dpkg -i /tmp/pure-ftpd/pure-ftpd-postgresql_*.deb && \ - rm -Rf /tmp/pure-ftpd - -# prevent pure-ftpd upgrading -RUN apt-mark hold pure-ftpd pure-ftpd-common - -# setup ftpgroup and ftpuser -RUN groupadd ftpgroup &&\ - useradd -g ftpgroup -d /home/ftpusers -s /dev/null ftpuser - -# configure rsyslog logging -RUN echo "" >> /etc/rsyslog.conf && \ - echo "#PureFTP Custom Logging" >> /etc/rsyslog.conf && \ - echo "ftp.* /var/log/pure-ftpd/pureftpd.log" >> /etc/rsyslog.conf && \ - echo "Updated /etc/rsyslog.conf with /var/log/pure-ftpd/pureftpd.log" - -# setup run/init file -COPY run.sh /run.sh -# Remove \r from the windows style \r\n newline. -RUN sed -i -e "s/\r//" /run.sh -RUN chmod u+x /run.sh - -# cleaning up -RUN apt-get -y clean \ - && apt-get -y autoclean \ - && apt-get -y autoremove \ - && rm -rf /var/lib/apt/lists/* - -# default publichost, you'll need to set this for passive support -ENV PUBLICHOST localhost - -# couple available volumes you may want to use -VOLUME ["/home/ftpusers", "/etc/pure-ftpd/passwd"] - -# startup -CMD /run.sh -l puredb:/etc/pure-ftpd/pureftpd.pdb -E -j -R -P $PUBLICHOST - -EXPOSE 21 30000-30009 +# +# FluentFTP Integration Test Server: pureftpd +# + +FROM python:3-slim AS prebuild + +SHELL ["/bin/bash", "-c"] + +WORKDIR /usr/src/app +RUN pip install --user apt-smart + +WORKDIR /root +RUN python3 /root/.local/bin/apt-smart -b > deb_mirror + +# +# Stage 1: build & production +# + +FROM debian:bullseye-slim AS build + +LABEL Description="FluentFTP pureftpd docker image based on Debian Bullseye." + +SHELL ["/bin/bash", "-c"] + +ARG DEBIAN_FRONTEND=noninteractive +ARG APT_CMD='apt install -y --no-install-recommends' + +COPY --from=prebuild /root/deb_mirror /root/deb_mirror + +WORKDIR / +RUN mapfile -t lines < /root/deb_mirror && \ + DEB_MIRROR=${lines[0]} && \ + echo $DEB_MIRROR && \ + \ + printf "\ + deb $DEB_MIRROR bullseye main\n\ +# deb-src $DEB_MIRROR bullseye main\n\ + \n\ + deb http://deb.debian.org/debian-security bullseye-security main contrib\n\ +# deb-src http://deb.debian.org/debian-security bullseye-security main contrib\n\ + \n\ + # bullseye-updates, previously known as 'volatile'\n\ + deb $DEB_MIRROR bullseye-updates main\n\ +# deb-src $DEB_MIRROR bullseye-updates main\n\ + " > /etc/apt/sources.list + +RUN apt update && apt upgrade -y && apt install -y apt-utils && \ + \ + $APT_CMD \ + openssl \ + pure-ftpd + +COPY run-pureftpd.sh /usr/sbin/ + +RUN sed -i -e "s/\r//" /usr/sbin/run-pureftpd.sh && \ + chmod +x /usr/sbin/run-pureftpd.sh && \ + \ + useradd -m -p savatlcb.1m26 fluentuser && \ + \ + mkdir -p /home/fluentuser/ && \ + chown -R fluentuser:users /home/fluentuser && \ + \ + openssl req -x509 -newkey rsa:4096 \ + -keyout /etc/ssl/private/pure-ftpd.key -out /etc/ssl/certs/pure-ftpd.crt \ + -subj "/C=US/ST=State/L=/O=Dev/CN=fluentftp" \ + -nodes -days 3650 && \ + \ + chmod 0600 /etc/ssl/private/pure-ftpd.key && \ + chmod 0640 /etc/ssl/private/pure-ftpd.key && \ + \ + cat /etc/ssl/certs/pure-ftpd.crt /etc/ssl/private/pure-ftpd.key > /etc/ssl/private/pure-ftpd.pem + +VOLUME ["/home/fluentuser", "/var/log/pureftpd"] + +EXPOSE 20 21 + +CMD ["/usr/sbin/run-pureftpd.sh"] diff --git a/FluentFTP.Dockers/pureftpd/LICENSE b/FluentFTP.Dockers/pureftpd/LICENSE deleted file mode 100644 index fdef6e12c..000000000 --- a/FluentFTP.Dockers/pureftpd/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2017 Andrew Stilliard - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/FluentFTP.Dockers/pureftpd/Makefile b/FluentFTP.Dockers/pureftpd/Makefile deleted file mode 100644 index fd850b4c3..000000000 --- a/FluentFTP.Dockers/pureftpd/Makefile +++ /dev/null @@ -1,72 +0,0 @@ -.PHONY: test test-tls build run run-tls kill enter setup-bob test-bob push pull - -test: build run logs-for-5 setup-bob test-bob - -test-tls: build run-tls logs-for-5 test-bob-tls - -# tail logs for a set number of seconds -logs-for-%: - @echo "-----" - @echo "watching logs for next $* seconds" - @echo "-----" - -timeout -s9 $* sudo docker logs -f ftpd_server - -build: - sudo docker build --rm -t pure-ftp-demo . - -run: kill - sudo docker run -d --name ftpd_server -p 21:21 -p 30000-30009:30000-30009 -e "PUBLICHOST=localhost" -e "ADDED_FLAGS=-d -d" pure-ftp-demo - -# runs with auto generated tls cert & creates test bob user -run-tls: kill - -sudo docker volume rm ftp_tls - sudo docker volume create --name ftp_tls - sudo docker run -d --name ftpd_server -p 21:21 -p 30000-30009:30000-30009 -e "PUBLICHOST=localhost" -e "ADDED_FLAGS=-d -d --tls 2" -e "TLS_CN=localhost" -e "TLS_ORG=Demo" -e "TLS_C=UK" -e"TLS_USE_DSAPRAM=true" -e FTP_USER_NAME=bob -e FTP_USER_PASS=test -e FTP_USER_HOME=/home/ftpusers/bob -v ftp_tls:/etc/ssl/private/ pure-ftp-demo - -kill: - -sudo docker kill ftpd_server - -sudo docker rm ftpd_server - -enter: - sudo docker exec -it ftpd_server sh -c "export TERM=xterm && bash" - -# Setup test "bob" user with "test" as password -setup-bob: - sudo docker exec -it ftpd_server sh -c "(echo test; echo test) | pure-pw useradd bob -f /etc/pure-ftpd/passwd/pureftpd.passwd -m -u ftpuser -d /home/ftpusers/bob" - @echo "User bob setup with password: test" - -# simple test to list files, upload a file, download it to a new name, delete it via ftp and read the new local one to make sure it's in tact -test-bob: - echo "Test file was read successfully!" > test-orig-file.txt - echo "user bob test\n\ - ls -alh\n\ - put test-orig-file.txt\n\ - ls -alh\n\ - get test-orig-file.txt test-new-file.txt\n\ - delete test-orig-file.txt\n\ - ls -alh" | ftp -n -v -p localhost 21 - cat test-new-file.txt - rm test-orig-file.txt test-new-file.txt - -# test again but with tls (uses lftp for tls support) -test-bob-tls: - echo "Test file was read successfully!" > test-orig-file.txt - cert="$$(sudo docker volume inspect --format '{{ .Mountpoint }}' ftp_tls)/pure-ftpd.pem";\ - echo "ls -alh\n\ - put test-orig-file.txt\n\ - echo '~ uploaded file ~'\n\ - ls -alh\n\ - get test-orig-file.txt -o test-new-file.txt\n\ - rm test-orig-file.txt\n\ - echo '~ removed file ~'\n\ - ls -alh" | sudo lftp -u bob,test -e "set ssl:ca-file '$$cert'" localhost 21 - cat test-new-file.txt - sudo rm test-orig-file.txt test-new-file.txt - -# git commands for quick chaining of make commands -push: - git push --all - git push --tags - -pull: - git pull diff --git a/FluentFTP.Dockers/pureftpd/README.md b/FluentFTP.Dockers/pureftpd/README.md deleted file mode 100644 index a191d7737..000000000 --- a/FluentFTP.Dockers/pureftpd/README.md +++ /dev/null @@ -1,323 +0,0 @@ -Docker Pure-ftpd Server -============================ -https://hub.docker.com/r/stilliard/pure-ftpd/ - -[![Build Status](https://travis-ci.org/stilliard/docker-pure-ftpd.svg?branch=master)](https://travis-ci.org/stilliard/docker-pure-ftpd) -[![Docker Build Status](https://img.shields.io/docker/cloud/automated/stilliard/pure-ftpd)](https://hub.docker.com/r/stilliard/pure-ftpd/) -[![Docker Pulls](https://img.shields.io/docker/pulls/stilliard/pure-ftpd.svg)](https://hub.docker.com/r/stilliard/pure-ftpd/) -[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fstilliard%2Fdocker-pure-ftpd.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fstilliard%2Fdocker-pure-ftpd?ref=badge_shield) -[![Sponsor Project](https://img.shields.io/badge/%E2%99%A5-Sponsor_Project-blueviolet)](https://github.com/sponsors/stilliard) - - ----------------------------------------- - -#### Check out our [basic example workflow](https://github.com/stilliard/docker-pure-ftpd/wiki/Basic-example-walk-through) & our [slightly more advanced workflow with tls & an auto created user](https://github.com/stilliard/docker-pure-ftpd/wiki/Advanced-example-walk-through-with-TLS-&-automatic-user-account). - ----------------------------------------- - -Pull down latest version with docker: -```bash -docker pull stilliard/pure-ftpd -``` - -**Often needing to run as `sudo`, e.g. `sudo docker pull stilliard/pure-ftpd`** - ----------------------------------------- - -**If you want to make changes, my advice is to either change the run command when running it or extend this image to make any changes rather than forking the project.** -This is because rebuilding the entire docker image via a fork can be *very* slow as it rebuilds the entire pure-ftpd package from source. - -To change the command run on start you could use the `command:` option if using `docker-compose`, or with [`docker run`](https://docs.docker.com/engine/reference/run/) directly you could use: - -``` -docker run --rm -d --name ftpd_server -p 21:21 -p 30000-30009:30000-30009 stilliard/pure-ftpd bash /run.sh -c 30 -C 10 -l puredb:/etc/pure-ftpd/pureftpd.pdb -E -j -R -P localhost -p 30000:30059 -``` - -To extend it you can create a new project with a `DOCKERFILE` like so: - -``` -FROM stilliard/pure-ftpd - -# e.g. you could change the defult command run: -CMD /run.sh -c 30 -C 10 -l puredb:/etc/pure-ftpd/pureftpd.pdb -E -j -R -P $PUBLICHOST -p 30000:30059 -``` - -*Then you can build your own image, `docker build --rm -t my-pure-ftp .`, where my-pure-ftp is the name you want to build as* - ----------------------------------------- - -Starting it ------------------------------- - -`docker run -d --name ftpd_server -p 21:21 -p 30000-30009:30000-30009 -e "PUBLICHOST=localhost" stilliard/pure-ftpd` - -*Or for your own image, replace stilliard/pure-ftpd with the name you built it with, e.g. my-pure-ftp* - -You can also pass ADDED_FLAGS as an env variable to add additional options such as --tls to the pure-ftpd command. -e.g. ` -e "ADDED_FLAGS=--tls=2" ` - - -Operating it ------------------------------- - -`docker exec -it ftpd_server /bin/bash` - -Setting runtime FTP user ------------------------------- - -To create a user on the ftp container, use the following environment variables: `FTP_USER_NAME`, `FTP_USER_PASS` and `FTP_USER_HOME`. - -`FTP_USER_HOME` is the root directory of the new user. - -Example usage: - -`docker run -e FTP_USER_NAME=bob -e FTP_USER_PASS=12345 -e FTP_USER_HOME=/home/bob stilliard/pure-ftpd` - -If you wish to set the `UID` & `GID` of the FTP user, use the `FTP_USER_UID` & `FTP_USER_GID` environment variables. - -Using different passive ports ------------------------------- - -To use passive ports in a different range (*eg*: `10000-10009`), use the following setup: - -`docker run -e FTP_PASSIVE_PORTS=10000:10009 --expose=10000-10009 -p 21:21 -p 10000-10009:10000-10009` - -You may need the `--expose=` option, because default passive ports exposed are `30000` to `30009`. - -Example usage once inside ------------------------------- - -Create an ftp user: `e.g. bob with chroot access only to /home/ftpusers/bob` -```bash -pure-pw useradd bob -f /etc/pure-ftpd/passwd/pureftpd.passwd -m -u ftpuser -d /home/ftpusers/bob -``` -*No restart should be needed.* - -*If you have any trouble with volume permissions due to the **uid** or **gid** of the created user you can change the **-u** flag for the uid you would like to use and/or specify **-g** with the group id as well. For more information see issue [#35](https://github.com/stilliard/docker-pure-ftpd/issues/35#issuecomment-325583705).* - -More info on usage here: https://download.pureftpd.org/pure-ftpd/doc/README.Virtual-Users - - -Test your connection -------------------------- -From the host machine: -```bash -ftp -p localhost 21 -``` - -------------------------- - -Docker compose -------------------------- -Docker compose can help you simplify the orchestration of your containers. -We have a simple [example of the docker compose](https://github.com/stilliard/docker-pure-ftpd/blob/master/docker-compose.yml). -& here's a [more detailed example using wordpress](https://github.com/stilliard/docker-pure-ftpd/wiki/Docker-stack-with-Wordpress-&-FTP) with ftp using this image. - -------------------------- - -Max clients -------------------------- -By default we set 5 max clients at once, but you can increase this by using the following environment variable `FTP_MAX_CLIENTS`, e.g. to `FTP_MAX_CLIENTS=50` and then also increasing the number of public ports opened from `FTP_PASSIVE_PORTS=30000:30009` `FTP_PASSIVE_PORTS=30000:30099`. You'll also want to open those ports when running docker run. -In addition you can specify the maximum connections per ip by setting the environment variable `FTP_MAX_CONNECTIONS`. By default the value is 5. - -All Pure-ftpd flags available: --------------------------------------- -https://linux.die.net/man/8/pure-ftpd - -Logs -------------------------- -To get verbose logs add the following to your `docker run` command: -``` --e "ADDED_FLAGS=-d -d" -``` - -Then the logs will be redirected to the stdout of the container and captured by the docker log collector. -You can watch them with `docker logs -f ftpd_server` - -Or, if you exec into the container you could watch over the log with `tail -f /var/log/messages` - -Want a transfer log file? add the following to your `docker run` command: -```bash --e "ADDED_FLAGS=-O w3c:/var/log/pure-ftpd/transfer.log" -``` - ----------------------------------------- - -Tags available for different versions --------------------------------------- - -**Latest versions** - -- `latest` - latest working version -- `jessie-latest` - latest but will always remain on debian jessie -- `hardened` - latest + [added security defaults](https://github.com/stilliard/docker-pure-ftpd/issues/10) - -**Previous version before tags were introduced** - -- `wheezy-1.0.36` - incase you want to roll back to before we started using debian jessie - -**Specific pure-ftpd versions** - -- `jessie-1.x.x` - jessie + specific versions, e.g. jessie-1.0.36 -- `hardened-1.x.x` - hardened + specific versions - -*Check the tags on github for available versions, feel free to submit issues and/or pull requests for newer versions* - -Usage of specific tags: -`sudo docker pull stilliard/pure-ftpd:hardened-1.0.36` - -**An arm64 build is also available here:** https://hub.docker.com/r/zhabba/pure-ftpd-arm64 *- Thanks @zhabba* - ----------------------------------------- - -Our default pure-ftpd options explained ----------------------------------------- - -``` -/usr/sbin/pure-ftpd # path to pure-ftpd executable --c 5 # --maxclientsnumber (no more than 5 people at once) --C 5 # --maxclientsperip (no more than 5 requests from the same ip) --l puredb:/etc/pure-ftpd/pureftpd.pdb # --login (login file for virtual users) --E # --noanonymous (only real users) --j # --createhomedir (auto create home directory if it doesnt already exist) --R # --nochmod (prevent usage of the CHMOD command) --P $PUBLICHOST # IP/Host setting for PASV support, passed in your the PUBLICHOST env var --p 30000:30009 # PASV port range (10 ports for 5 max clients) --tls 1 # Enables optional TLS support -``` - -For more information please see `man pure-ftpd`, or visit: https://www.pureftpd.org/ - -Why so many ports opened? ---------------------------- -This is for PASV support, please see: [#5 PASV not fun :)](https://github.com/stilliard/docker-pure-ftpd/issues/5) - ----------------------------------------- - -Docker Volumes --------------- -There are a few spots onto which you can mount a docker volume to configure the -server and persist uploaded data. It's recommended to use them in production. - - - `/home/ftpusers/` The ftp's data volume (by convention). - - `/etc/pure-ftpd/passwd` A directory containing the single `pureftpd.passwd` - file which contains the user database (i.e., all virtual users, their - passwords and their home directories). This is read on startup of the - container and updated by the `pure-pw useradd -f /etc/pure- - ftpd/passwd/pureftpd.passwd ...` command. - - `/etc/ssl/private/` A directory containing a single `pure-ftpd.pem` file - with the server's SSL certificates for TLS support. Optional TLS is - automatically enabled when the container finds this file on startup. - -Keep user database in a volume ------------------------------- -You may want to keep your user database through the successive image builds. It is possible with Docker volumes. - -Create a named volume: -``` -docker volume create --name my-db-volume -``` - -Specify it when running the container: -``` -docker run -d --name ftpd_server -p 21:21 -p 30000-30009:30000-30009 -e "PUBLICHOST=localhost" -v my-db-volume:/etc/pure-ftpd/passwd stilliard/pure-ftpd -``` - -When an user is added, you need to use the password file which is in the volume: -``` -pure-pw useradd bob -f /etc/pure-ftpd/passwd/pureftpd.passwd -m -u ftpuser -d /home/ftpusers/bob -``` -(Thanks to the -m option, you don't need to call *pure-pw mkdb* with this syntax). - - -Changing a password ---------------------- -e.g. to change the password for user "bob": -``` -pure-pw passwd bob -f /etc/pure-ftpd/passwd/pureftpd.passwd -m -``` - ----------------------------------------- -Development (via git clone) -```bash -# Clone the repo -git clone https://github.com/stilliard/docker-pure-ftpd.git -cd docker-pure-ftpd -# Build the image -make build -# Run container in background: -make run -# enter a bash shell inside the container: -make enter -# test that it's all working with -make test -``` - -TLS ----- - -If you want to enable tls (for ftps connections), you need to have a valid -certificate. You can get one from one of the certificate authorities that you'll -find when googling this topic. The certificate (containing private key and -certificate) needs to be at: - -``` -/etc/ssl/private/pure-ftpd.pem -``` - -Use docker volumes to get the certificate there at runtime. The container will -automatically enable optional TLS when it detect the file at this location. - -You can also self-sign a certificate, which is certainly the easiest way to -start out. Self signed certificates come with certain drawbacks, but it might -be better to have a self signed one than none at all. - -Here's how to create a self-signed certificate from within the container: - -```bash -mkdir -p /etc/ssl/private -openssl dhparam -out /etc/ssl/private/pure-ftpd-dhparams.pem 2048 -openssl req -x509 -nodes -newkey rsa:2048 -sha256 -keyout \ - /etc/ssl/private/pure-ftpd.pem \ - -out /etc/ssl/private/pure-ftpd.pem -chmod 600 /etc/ssl/private/*.pem -``` - -Automatic TLS certificate generation ------------------------------- - -If `ADDED_FLAGS` contains `--tls` (e.g. --tls=1 or --tls=2) and file `/etc/ssl/private/pure-ftpd.pem` does not exists -it is possible to generate self-signed certificate if `TLS_CN`, `TLS_ORG` and `TLS_C` are set. - -Keep in mind that if no volume is set for `/etc/ssl/private/` directory generated -certificates won't be persisted and new ones will be generated on each start. - -You can also pass `-e "TLS_USE_DSAPRAM=true"` for faster generated certificates -though this option is not recommended for production. - -Please check out the [TLS docs here](https://download.pureftpd.org/pub/pure-ftpd/doc/README.TLS). - -TLS with cert and key file for Let's Encrypt ------------------------------- - -Let's Encrypt provides two separate files for certificate and keyfile. The [Pure-FTPd TLS encryption](https://download.pureftpd.org/pub/pure-ftpd/doc/README.TLS) documentation suggests to simply concat them into one file. -So you can simply provide the Let's Encrypt cert ``/etc/ssl/private/pure-ftpd-cert.pem`` and key ``/etc/ssl/private/pure-ftpd-key.pem`` via Docker Volumes and let them get auto-concatenated into ``/etc/ssl/private/pure-ftpd.pem``. -Or concat them manually with -```sh -cat /etc/letsencrypt/live//cert.pem /etc/letsencrypt/live//privkey.pem > pure-ftpd.pem -``` - - -Credits -------------- -Thanks for the help on stackoverflow with this! -https://stackoverflow.com/questions/23930167/installing-pure-ftpd-in-docker-debian-wheezy-error-421 - -Also thanks to all the awesome contributors that have made this project amazing! -https://github.com/stilliard/docker-pure-ftpd/graphs/contributors - -You can also help support the development of this project with coffee power: -Buy Me A Coffee - -## License -[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fstilliard%2Fdocker-pure-ftpd.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2Fstilliard%2Fdocker-pure-ftpd?ref=badge_large) diff --git a/FluentFTP.Dockers/pureftpd/docker-compose.yml b/FluentFTP.Dockers/pureftpd/docker-compose.yml index e2124a2fc..6ec9eb5dd 100644 --- a/FluentFTP.Dockers/pureftpd/docker-compose.yml +++ b/FluentFTP.Dockers/pureftpd/docker-compose.yml @@ -1,27 +1,15 @@ -version: '3' - -# Usage example: https://github.com/stilliard/docker-pure-ftpd/wiki/Docker-stack-with-Wordpress-&-FTP - services: - ftpd_server: - image: stilliard/pure-ftpd - container_name: pure-ftpd - ports: - - "21:21" - - "30000-30009:30000-30009" - volumes: # remember to replace /folder_on_disk/ with the path to where you want to store the files on the host machine - - "/folder_on_disk/data:/home/username/" - - "/folder_on_disk/passwd:/etc/pure-ftpd/passwd" -# uncomment for ssl/tls, see https://github.com/stilliard/docker-pure-ftpd#tls -# - "/folder_on_disk/ssl:/etc/ssl/private/" -# or ssl/tls with Let's Encrypt (cert and key as two files) -# - "/etc/letsencrypt/live//cert.pem:/etc/ssl/private/pure-ftpd-cert.pem" -# - "/etc/letsencrypt/live//privkey.pem:/etc/ssl/private/pure-ftpd-key.pem" - environment: - PUBLICHOST: "localhost" - FTP_USER_NAME: username - FTP_USER_PASS: mypass - FTP_USER_HOME: /home/username -# also for ssl/tls: -# ADDED_FLAGS: "--tls=2" + pureftpd: + build: + context: . + network: host + restart: unless-stopped restart: always + network_mode: "host" + ports: + - 0.0.0.0:20:20 + - 0.0.0.0:21:21 + - 21100-21199:21100-21199 + volumes: + - ./home:/home/pureftpd + - ./logs:/var/log/pureftpd diff --git a/FluentFTP.Dockers/pureftpd/run-pureftpd.sh b/FluentFTP.Dockers/pureftpd/run-pureftpd.sh new file mode 100644 index 000000000..6d11cd497 --- /dev/null +++ b/FluentFTP.Dockers/pureftpd/run-pureftpd.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +# stdout server info: +cat << EOB + ************************************************* + * * + * Docker image: fluentftp pureftpd * + * * + ************************************************* + + SERVER SETTINGS + --------------- + · FTP User: fluentuser + · FTP Password: fluentpass +EOB + +if [[ -n "${USE_SSL}" ]]; then + TLS=1 +else + TLS=0 +fi + +# Run pureftpd: +&>/dev/null /usr/sbin/pure-ftpd -A -E -j -R -l unix -p 21100:21199 --tls $TLS diff --git a/FluentFTP.Dockers/pureftpd/run.sh b/FluentFTP.Dockers/pureftpd/run.sh deleted file mode 100644 index e6c8ddec8..000000000 --- a/FluentFTP.Dockers/pureftpd/run.sh +++ /dev/null @@ -1,151 +0,0 @@ -#!/bin/bash - -# build up flags passed to this file on run + env flag for additional flags -# e.g. -e "ADDED_FLAGS=--tls=2" -PURE_FTPD_FLAGS=" $@ $ADDED_FLAGS " - -# start rsyslog -if [[ "$PURE_FTPD_FLAGS" == *" -d "* ]] || [[ "$PURE_FTPD_FLAGS" == *"--verboselog"* ]] -then - echo "Log enabled, see /var/log/messages" - rsyslogd - rm -rf /var/log/pure-ftpd/pureftpd.log - tail --pid $$ -F /var/log/pure-ftpd/pureftpd.log & -fi - -PASSWD_FILE="/etc/pure-ftpd/passwd/pureftpd.passwd" - -# Load in any existing db from volume store -if [ -e /etc/pure-ftpd/passwd/pureftpd.passwd ] -then - pure-pw mkdb /etc/pure-ftpd/pureftpd.pdb -f "$PASSWD_FILE" -fi - -# detect if using TLS (from volumed in file) but no flag set, set one -if [ -e /etc/ssl/private/pure-ftpd.pem ] && [[ "$PURE_FTPD_FLAGS" != *"--tls"* ]] && [[ "$PURE_FTPD_FLAGS" != *"-Y"* ]] -then - echo "TLS Enabled" - PURE_FTPD_FLAGS="$PURE_FTPD_FLAGS --tls=1 " -fi - -# If TLS flag is set and cert and key are given are given as two files, merge them into one cert -if [ -e /etc/ssl/private/pure-ftpd-cert.pem ] && [ -e /etc/ssl/private/pure-ftpd-key.pem ] && [[ "$PURE_FTPD_FLAGS" == *"--tls"* ]] -then - echo "Merging certificate and key" - cat /etc/ssl/private/pure-ftpd-cert.pem /etc/ssl/private/pure-ftpd-key.pem > /etc/ssl/private/pure-ftpd.pem -fi - -# If TLS flag is set and no certificate exists, generate it -if [ ! -e /etc/ssl/private/pure-ftpd.pem ] && [[ "$PURE_FTPD_FLAGS" == *"--tls"* ]] && [ ! -z "$TLS_CN" ] && [ ! -z "$TLS_ORG" ] && [ ! -z "$TLS_C" ] -then - echo "Generating self-signed certificate" - mkdir -p /etc/ssl/private - if [[ "$TLS_USE_DSAPRAM" == "true" ]]; then - openssl dhparam -dsaparam -out /etc/ssl/private/pure-ftpd-dhparams.pem 2048 - else - openssl dhparam -out /etc/ssl/private/pure-ftpd-dhparams.pem 2048 - fi - openssl req -subj "/CN=${TLS_CN}/O=${TLS_ORG}/C=${TLS_C}" -days 1826 \ - -x509 -nodes -newkey rsa:2048 -sha256 -keyout \ - /etc/ssl/private/pure-ftpd.pem \ - -out /etc/ssl/private/pure-ftpd.pem - chmod 600 /etc/ssl/private/*.pem -fi - -# Add user -if [ ! -z "$FTP_USER_NAME" ] && [ ! -z "$FTP_USER_PASS" ] && [ ! -z "$FTP_USER_HOME" ] -then - echo "Creating user..." - - # make sure the home folder exists - mkdir -p "$FTP_USER_HOME" - - # Generate the file that will be used to inject in the password prompt stdin - PWD_FILE="$(mktemp)" - echo "$FTP_USER_PASS -$FTP_USER_PASS" > "$PWD_FILE" - - # Set uid/gid - PURE_PW_ADD_FLAGS="" - if [ ! -z "$FTP_USER_UID" ] - then - PURE_PW_ADD_FLAGS="$PURE_PW_ADD_FLAGS -u $FTP_USER_UID" - else - PURE_PW_ADD_FLAGS="$PURE_PW_ADD_FLAGS -u ftpuser" - fi - if [ ! -z "$FTP_USER_GID" ] - then - PURE_PW_ADD_FLAGS="$PURE_PW_ADD_FLAGS -g $FTP_USER_GID" - fi - - pure-pw useradd "$FTP_USER_NAME" -f "$PASSWD_FILE" -m -d "$FTP_USER_HOME" $PURE_PW_ADD_FLAGS < "$PWD_FILE" - - if [ ! -z "$FTP_USER_HOME_PERMISSION" ] - then - chmod "$FTP_USER_HOME_PERMISSION" "$FTP_USER_HOME" - echo " root user give $FTP_USER_NAME ftp user at $FTP_USER_HOME directory has $FTP_USER_HOME_PERMISSION permission" - fi - - if [ ! -z "$FTP_USER_UID" ] - then - if ! [[ $(ls -ldn $FTP_USER_HOME | awk '{print $3}') = $FTP_USER_UID ]] - then - chown $FTP_USER_UID "$FTP_USER_HOME" - echo " root user give $FTP_USER_HOME directory $FTP_USER_UID owner" - fi - else - if ! [[ $(ls -ld $FTP_USER_HOME | awk '{print $3}') = 'ftpuser' ]] - then - chown ftpuser "$FTP_USER_HOME" - echo " root user give $FTP_USER_HOME directory ftpuser owner" - fi - fi - - rm "$PWD_FILE" -fi - -# Set a default value to the env var FTP_PASSIVE_PORTS -if [ -z "$FTP_PASSIVE_PORTS" ] -then - FTP_PASSIVE_PORTS=30000:30009 -fi - -# Set passive port range in pure-ftpd options if not already existent -if [[ $PURE_FTPD_FLAGS != *" -p "* ]] -then - echo "Setting default port range to: $FTP_PASSIVE_PORTS" - PURE_FTPD_FLAGS="$PURE_FTPD_FLAGS -p $FTP_PASSIVE_PORTS" -fi - -# Set a default value to the env var FTP_MAX_CLIENTS -if [ -z "$FTP_MAX_CLIENTS" ] -then - FTP_MAX_CLIENTS=5 -fi - -# Set max clients in pure-ftpd options if not already existent -if [[ $PURE_FTPD_FLAGS != *" -c "* ]] -then - echo "Setting default max clients to: $FTP_MAX_CLIENTS" - PURE_FTPD_FLAGS="$PURE_FTPD_FLAGS -c $FTP_MAX_CLIENTS" -fi - -# Set a default value to the env var FTP_MAX_CONNECTIONS -if [ -z "$FTP_MAX_CONNECTIONS" ] -then - FTP_MAX_CONNECTIONS=5 -fi - -# Set max connections per ip in pure-ftpd options if not already existent -if [[ $PURE_FTPD_FLAGS != *" -C "* ]] -then - echo "Setting default max connections per ip to: $FTP_MAX_CONNECTIONS" - PURE_FTPD_FLAGS="$PURE_FTPD_FLAGS -C $FTP_MAX_CONNECTIONS" -fi - -# let users know what flags we've ended with (useful for debug) -echo "Starting Pure-FTPd:" -echo " pure-ftpd $PURE_FTPD_FLAGS" - -# start pureftpd with requested flags -exec /usr/sbin/pure-ftpd $PURE_FTPD_FLAGS diff --git a/FluentFTP.Tests/Integration/IntegrationTests.cs b/FluentFTP.Tests/Integration/IntegrationTests.cs index f7c514421..83c1d1850 100644 --- a/FluentFTP.Tests/Integration/IntegrationTests.cs +++ b/FluentFTP.Tests/Integration/IntegrationTests.cs @@ -28,6 +28,14 @@ public async Task ProFtpd() { public async Task ProFtpdSsl() { await IntegrationTestRunner.Run(FtpServer.ProFTPD, UseSsl); } + [Fact] + public async Task PureFtpd() { + await IntegrationTestRunner.Run(FtpServer.PureFTPd); + } + [Fact] + public async Task PureFtpdSsl() { + await IntegrationTestRunner.Run(FtpServer.PureFTPd, UseSsl); + } // These can only do FTPS [Fact] @@ -48,10 +56,6 @@ public async Task Bftpd() { // Still need SSL variants of these [Fact] - public async Task PureFtpd() { - await IntegrationTestRunner.Run(FtpServer.PureFTPd); - } - [Fact] public async Task PyFtpdLib() { await IntegrationTestRunner.Run(FtpServer.PyFtpdLib); } diff --git a/FluentFTP.Xunit/Docker/Containers/PureFtpdContainer.cs b/FluentFTP.Xunit/Docker/Containers/PureFtpdContainer.cs index 47b3397cb..b4724a671 100644 --- a/FluentFTP.Xunit/Docker/Containers/PureFtpdContainer.cs +++ b/FluentFTP.Xunit/Docker/Containers/PureFtpdContainer.cs @@ -13,9 +13,10 @@ public PureFtpdContainer() { ServerType = FtpServer.PureFTPd; ServerName = "pureftpd"; DockerImage = "pureftpd:fluentftp"; - DockerImageOriginal = "stilliard/pure-ftpd"; - DockerGithub = "https://github.com/stilliard/docker-pure-ftpd"; - //RunCommand = "docker run -d --name ftpd_server -p 21:21 -p 30000-30009:30000-30009 -e \"PUBLICHOST=localhost\" -e \"FTP_USER_NAME=fluentroot\" -e \"FTP_USER_PASS=fluentpass\" pureftpd:fluentftp"; + //without SSL: + // RunCommand = "docker run --rm -it -p 21:21 -p 21100-21199:21100-21199 pureftpd:fluentftp"; + //with SSL: + // RunCommand = "docker run --rm -it -p 21:21 -p 21100-21199:21100-21199 -e USE_SSL=YES pureftpd:fluentftp"; } /// @@ -24,12 +25,15 @@ public PureFtpdContainer() { public override ITestcontainersBuilder Configure(ITestcontainersBuilder builder) { - builder = ExposePortRange(builder, 30000, 30009); + builder = builder.WithPortBinding(20); - builder = builder - .WithEnvironment("FTP_USER_NAME", DockerFtpConfig.FtpUser) - .WithEnvironment("FTP_USER_PASS", DockerFtpConfig.FtpPass) - .WithEnvironment("FTP_USER_HOME", "/home/bob"); + builder = ExposePortRange(builder, 21100, 21199); + + builder = builder.WithCreateContainerParametersModifier(x => { + x.HostConfig.CapAdd = new List { + "ALL" + }; + }); return builder; }