6 Commits

Author SHA1 Message Date
d81f3fe81b Fix FTP_PASV_ADDRESS setting 2025-05-08 22:52:04 +02:00
b85c56d67e add compose project name 2025-05-06 22:41:34 +02:00
846f492187 update README 2025-05-06 22:30:26 +02:00
1345bbd50e update base image; add compose file 2025-05-06 22:15:57 +02:00
Andrew Cutler
19008464f4 dont always tag latest 2019-12-02 15:21:27 +11:00
Andrew Cutler
dcb7216288 update year 2019-12-02 15:21:20 +11:00
11 changed files with 88 additions and 36 deletions

5
.gitignore vendored
View File

@@ -1,4 +1,7 @@
*.swp *.swp
srv/ srv/
env config/
logs/
data/
.env
vsftpd.pem vsftpd.pem

View File

@@ -1,4 +1,7 @@
FROM debian:stretch FROM debian:stable
LABEL maintainer="Luca Derderian <luca@wululu.de>"
LABEL version="${VERSION:-2.0}"
ARG FTP_UID=48 ARG FTP_UID=48
ARG FTP_GID=48 ARG FTP_GID=48
@@ -9,24 +12,25 @@ RUN set -x \
RUN set -x \ RUN set -x \
&& apt-get update \ && apt-get update \
&& apt-get install -y --no-install-recommends vsftpd db5.3-util whois \ && apt-get -y full-upgrade \
&& apt-get install -y --no-install-recommends vsftpd db-util whois gettext-base \
&& apt-get clean \ && apt-get clean \
&& rm -rf /var/lib/apt/lists/* \ && rm -rf /var/lib/apt/lists/* \
; ;
RUN set -x \ RUN set -x \
&& mkdir -p /var/run/vsftpd/empty /etc/vsftpd/user_conf /var/ftp /srv \ && mkdir -p /var/run/vsftpd/empty /etc/vsftpd/user_conf /var/ftp /srv /templates \
&& touch /var/log/vsftpd.log \ && touch /var/log/vsftpd.log \
&& rm -rf /srv/ftp \ && rm -rf /srv/ftp \
; ;
COPY vsftpd*.conf /etc/ COPY vsftpd*.conf /templates/
COPY vsftpd_virtual /etc/pam.d/ COPY vsftpd_virtual /etc/pam.d/
COPY *.sh / COPY *.sh /
VOLUME ["/etc/vsftpd", "/srv"] VOLUME ["/etc/vsftpd", "/srv"]
EXPOSE 21 4559 4560 4561 4562 4563 4564 EXPOSE 21
ENTRYPOINT ["/entry.sh"] ENTRYPOINT ["/entry.sh"]
CMD ["vsftpd"] CMD ["vsftpd"]

View File

@@ -1,6 +1,6 @@
The MIT License (MIT) The MIT License (MIT)
Copyright (c) 2015 Volt Grid Pty Ltd Copyright (c) 2015-2019 Volt Grid Pty Ltd
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
@@ -19,4 +19,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 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 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.

View File

@@ -7,7 +7,7 @@ help:
@printf "$$(grep -hE '^\S+:.*##' $(MAKEFILE_LIST) | sed -e 's/:.*##\s*/:/' -e 's/^\(.\+\):\(.*\)/\\x1b[36m\1\\x1b[m:\2/' | column -c2 -t -s :)\n" @printf "$$(grep -hE '^\S+:.*##' $(MAKEFILE_LIST) | sed -e 's/:.*##\s*/:/' -e 's/^\(.\+\):\(.*\)/\\x1b[36m\1\\x1b[m:\2/' | column -c2 -t -s :)\n"
build: ## Build for publishing build: ## Build for publishing
docker build --pull -t $(IMAGE_NAME):latest . docker build --pull -t $(IMAGE_NAME):$(TAG) .
build-local: ## Builds with local users UID and GID build-local: ## Builds with local users UID and GID
docker build --build-arg FTP_UID=$(shell id -u) --build-arg FTP_GID=$(shell id -g) -t $(IMAGE_NAME):$(TAG) . docker build --build-arg FTP_UID=$(shell id -u) --build-arg FTP_GID=$(shell id -g) -t $(IMAGE_NAME):$(TAG) .
@@ -16,34 +16,28 @@ bash:
docker run --rm -it $(IMAGE_NAME):$(TAG) bash docker run --rm -it $(IMAGE_NAME):$(TAG) bash
env: env:
@echo "FTP_USER=ftp" >> env @echo "FTP_USER=ftp" >> .env
@echo "FTP_PASSWORD=ftp" >> env @echo "FTP_PASSWORD=ftp" >> .env
vsftpd.pem: vsftpd.pem:
openssl req -new -newkey rsa:2048 -days 365 -nodes -sha256 -x509 -keyout vsftpd.pem -out vsftpd.pem -subj '/CN=self_signed' openssl req -new -newkey rsa:2048 -days 365 -nodes -sha256 -x509 -keyout vsftpd.pem -out vsftpd.pem -subj '/CN=self_signed'
run: env run: env
$(eval ID := $(shell docker run -d --env-file env -v $(shell pwd)/srv:/srv ${IMAGE_NAME}:${TAG})) $(eval ID := $(shell docker run -d --env-file .env -v $(shell pwd)/srv:/srv ${IMAGE_NAME}:${TAG}))
$(eval IP := $(shell docker inspect --format '{{ .NetworkSettings.IPAddress }}' ${ID})) $(eval IP := $(shell docker inspect --format '{{ .NetworkSettings.IPAddress }}' ${ID}))
@echo "Running ${ID} @ ftp://${IP}" @echo "Running ${ID} @ ftp://${IP}"
@docker attach ${ID} @docker attach ${ID}
@docker kill ${ID} @docker kill ${ID}
run-ssl: env vsftpd.pem run-ssl: env vsftpd.pem
$(eval ID := $(shell docker run -d --env-file env -v $(shell pwd)/srv:/srv -v $(PWD)/vsftpd.pem:/etc/ssl/certs/vsftpd.crt -v $(PWD)/vsftpd.pem:/etc/ssl/private/vsftpd.key ${IMAGE_NAME}:${TAG} vsftpd /etc/vsftpd_ssl.conf)) $(eval ID := $(shell docker run -d --env-file .env -v $(shell pwd)/srv:/srv -v $(PWD)/vsftpd.pem:/etc/ssl/certs/vsftpd.crt -v $(PWD)/vsftpd.pem:/etc/ssl/private/vsftpd.key ${IMAGE_NAME}:${TAG} vsftpd /etc/vsftpd_ssl.conf))
$(eval IP := $(shell docker inspect --format '{{ .NetworkSettings.IPAddress }}' ${ID})) $(eval IP := $(shell docker inspect --format '{{ .NetworkSettings.IPAddress }}' ${ID}))
@echo "Running ${ID} @ ftp://${IP}" @echo "Running ${ID} @ ftp://${IP}"
@docker attach ${ID} @docker attach ${ID}
@docker kill ${ID} @docker kill ${ID}
push: ## Pushes the docker image to hub.docker.com push: ## Pushes the docker image to hub.docker.com
# Don't --pull here, we don't want any last minute upsteam changes
docker build -t $(IMAGE_NAME):$(TAG) .
docker tag $(IMAGE_NAME):$(TAG) $(IMAGE_NAME):latest
docker push $(IMAGE_NAME):$(TAG) docker push $(IMAGE_NAME):$(TAG)
docker push $(IMAGE_NAME):latest
clean: ## Remove built images clean: ## Remove built images
docker rmi $(IMAGE_NAME):latest
docker rmi $(IMAGE_NAME):$(TAG) docker rmi $(IMAGE_NAME):$(TAG)

View File

@@ -2,6 +2,11 @@
This is a micro-service image for VSFTPD. This is a micro-service image for VSFTPD.
It is a fork from [panubo's docker-vsftpd](https://github.com/panubo/docker-vsftpd) (thanks!) and slightly modified to suit my needs:
* Update base image to `debian:latest`
* Support for configurable min and max port in passive mode
by templating the config files (via envsubst)
There are a few limitations but it will work if you are using host networking There are a few limitations but it will work if you are using host networking
`--net host` or have a direct/routed network between the Docker container and `--net host` or have a direct/routed network between the Docker container and
the client. the client.
@@ -33,8 +38,24 @@ which is in the _whois_ debian package.
- `FTP_PASV_ADDRESS`: override the IP address that vsftpd will advertise in - `FTP_PASV_ADDRESS`: override the IP address that vsftpd will advertise in
response to the PASV command response to the PASV command
- `FTP_PASV_MIN_PORT`: Minimum port for passive mode (remember to bind the ports if not used with compose file)
- `FTP_PASV_MAX_PORT`: Maximum port for passive mode (remember to bind the ports if not used with compose file)
## Usage Example ## Usage Example
### Docker Compose
First, setup your .env file by copying the sample file and modifying it to suit your needs.
```
cp env.sample .env
vi .env
```
Then run the stack
```
docker compose up -d
```
### Docker
``` ```
docker run --rm -it -p 21:21 -p 4559-4564:4559-4564 -e FTP_USER=ftp -e FTP_PASSWORD=ftp docker.io/panubo/vsftpd:latest docker run --rm -it -p 21:21 -p 4559-4564:4559-4564 -e FTP_USER=ftp -e FTP_PASSWORD=ftp docker.io/panubo/vsftpd:latest
``` ```
@@ -64,4 +85,4 @@ See [serverfault: vsftp: whu is allow_writable_chroot=YES a bad idea?](https://s
## Logs ## Logs
To get the FTP logs mount `/var/log` outside of the container. For example add `-v /var/log/ftp:/var/log` to your `docker run ...` command. To get the FTP logs mount `/var/log` outside of the container. For example add `-v /var/log/ftp:/var/log` to your `docker run ...` command or use `docker compose`.

View File

@@ -21,4 +21,4 @@ if [[ "${1}" == "-d" ]]; then
shift shift
fi fi
printf '%s\n%s\n' "${1}" "${2}" | db5.3_load -T -t hash "${DB}" printf '%s\n%s\n' "${1}" "${2}" | db_load -T -t hash "${DB}"

16
compose.yml Normal file
View File

@@ -0,0 +1,16 @@
services:
vsftpd:
container_name: vsftpd
image: wululu/vsftpd:${VERSION:-2.0}
build:
context: .
args:
VERSION: ${VERSION:-2.0}
volumes:
- ./data:/srv
- ./config:/etc/vsftpd
- ./logs:/var/log
ports:
- "${FTP_PORT:-21}:21"
- "${FTP_PASV_MIN_PORT:-4559}-${FTP_PASV_MAX_PORT:-4564}:${FTP_PASV_MIN_PORT:-4559}-${FTP_PASV_MAX_PORT:-4564}"
env_file: .env

View File

@@ -5,12 +5,21 @@ set -e
[[ "${DEBUG}" == "true" ]] && set -x [[ "${DEBUG}" == "true" ]] && set -x
# Replace variables in config files
for file in /templates/*; do
if [[ -f "$file" ]]; then
filename=$(basename "$file")
envsubst < "$file" > "/etc/$filename"
echo "Created /etc/${filename}"
fi
done
# Generate password if hash not set # Generate password if hash not set
if [[ ! -z "${FTP_PASSWORD}" ]] && [[ -z "${FTP_PASSWORD_HASH}" ]]; then if [[ -n "${FTP_PASSWORD}" ]] && [[ -z "${FTP_PASSWORD_HASH}" ]]; then
FTP_PASSWORD_HASH="$(echo "${FTP_PASSWORD}" | mkpasswd -s -m sha-512)" FTP_PASSWORD_HASH="$(echo "${FTP_PASSWORD}" | mkpasswd -s -m sha-512)"
fi fi
if [[ ! -z "${FTP_USER}" ]] || [[ ! -z "${FTP_PASSWORD_HASH}" ]]; then if [[ -n "${FTP_USER}" ]] || [[ -n "${FTP_PASSWORD_HASH}" ]]; then
/add-virtual-user.sh -d "${FTP_USER}" "${FTP_PASSWORD_HASH}" /add-virtual-user.sh -d "${FTP_USER}" "${FTP_PASSWORD_HASH}"
fi fi
@@ -22,20 +31,13 @@ while read -r user; do
done < <(env | grep "FTP_USER_" | sed 's/^\(FTP_USER_[a-zA-Z0-9]*\)=.*/\1/') done < <(env | grep "FTP_USER_" | sed 's/^\(FTP_USER_[a-zA-Z0-9]*\)=.*/\1/')
# Support user directories # Support user directories
if [[ ! -z "${FTP_USERS_ROOT}" ]]; then if [[ -n "${FTP_USERS_ROOT}" ]]; then
# shellcheck disable=SC2016 # shellcheck disable=SC2016
sed -i 's/local_root=.*/local_root=\/srv\/$USER/' /etc/vsftpd*.conf sed -i 's/local_root=.*/local_root=\/srv\/$USER/' /etc/vsftpd*.conf
fi fi
# Support setting the passive address
if [[ ! -z "$FTP_PASV_ADDRESS" ]]; then
for f in /etc/vsftpd*.conf; do
echo "pasv_address=${FTP_PASV_ADDRESS}" >> "$f"
done
fi
# Manage /srv permissions # Manage /srv permissions
if [[ ! -z "${FTP_CHOWN_ROOT}" ]]; then if [[ -n "${FTP_CHOWN_ROOT}" ]]; then
chown ftp:ftp /srv chown ftp:ftp /srv
fi fi

11
env.sample Normal file
View File

@@ -0,0 +1,11 @@
COMPOSE_PROJECT_NAME=vsftpd
VERSION=2.0
FTP_USER=
FTP_PASSWORD=
FTP_PORT=
FTP_PASV_ADDRESS=
FTP_PASV_MIN_PORT=
FTP_PASV_MAX_PORT=

View File

@@ -34,5 +34,6 @@ hide_ids=YES
connect_from_port_20=YES connect_from_port_20=YES
listen=YES listen=YES
tcp_wrappers=YES tcp_wrappers=YES
pasv_min_port=4559 pasv_address=${FTP_PASV_ADDRESS}
pasv_max_port=4564 pasv_min_port=${FTP_PASV_MIN_PORT}
pasv_max_port=${FTP_PASV_MAX_PORT}

View File

@@ -34,8 +34,9 @@ hide_ids=YES
connect_from_port_20=YES connect_from_port_20=YES
listen=YES listen=YES
tcp_wrappers=YES tcp_wrappers=YES
pasv_min_port=4559 pasv_address=${FTP_PASV_ADDRESS}
pasv_max_port=4564 pasv_min_port=${FTP_PASV_MIN_PORT}
pasv_max_port=${FTP_PASV_MAX_PORT}
# SSL # SSL
ssl_enable=Yes ssl_enable=Yes