8 Commits

Author SHA1 Message Date
d50d74505c Ignore .env* 2025-05-08 22:57:08 +02:00
8d310e4e59 Bump version to 2.1 2025-05-08 22:53:43 +02:00
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
srv/
env
config/
logs/
data/
.env*
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.1}"
ARG FTP_UID=48
ARG FTP_GID=48
@@ -9,24 +12,25 @@ RUN set -x \
RUN set -x \
&& 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 \
&& rm -rf /var/lib/apt/lists/* \
;
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 \
&& rm -rf /srv/ftp \
;
COPY vsftpd*.conf /etc/
COPY vsftpd*.conf /templates/
COPY vsftpd_virtual /etc/pam.d/
COPY *.sh /
VOLUME ["/etc/vsftpd", "/srv"]
EXPOSE 21 4559 4560 4561 4562 4563 4564
EXPOSE 21
ENTRYPOINT ["/entry.sh"]
CMD ["vsftpd"]

View File

@@ -1,6 +1,6 @@
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
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,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
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"
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
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
env:
@echo "FTP_USER=ftp" >> env
@echo "FTP_PASSWORD=ftp" >> env
@echo "FTP_USER=ftp" >> .env
@echo "FTP_PASSWORD=ftp" >> .env
vsftpd.pem:
openssl req -new -newkey rsa:2048 -days 365 -nodes -sha256 -x509 -keyout vsftpd.pem -out vsftpd.pem -subj '/CN=self_signed'
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}))
@echo "Running ${ID} @ ftp://${IP}"
@docker attach ${ID}
@docker kill ${ID}
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}))
@echo "Running ${ID} @ ftp://${IP}"
@docker attach ${ID}
@docker kill ${ID}
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):latest
clean: ## Remove built images
docker rmi $(IMAGE_NAME):latest
docker rmi $(IMAGE_NAME):$(TAG)

View File

@@ -2,6 +2,11 @@
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
`--net host` or have a direct/routed network between the Docker container and
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
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
### 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
```
@@ -64,4 +85,4 @@ See [serverfault: vsftp: whu is allow_writable_chroot=YES a bad idea?](https://s
## 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
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.1}
build:
context: .
args:
VERSION: ${VERSION:-2.1}
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
# 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
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)"
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}"
fi
@@ -22,20 +31,13 @@ while read -r user; do
done < <(env | grep "FTP_USER_" | sed 's/^\(FTP_USER_[a-zA-Z0-9]*\)=.*/\1/')
# Support user directories
if [[ ! -z "${FTP_USERS_ROOT}" ]]; then
if [[ -n "${FTP_USERS_ROOT}" ]]; then
# shellcheck disable=SC2016
sed -i 's/local_root=.*/local_root=\/srv\/$USER/' /etc/vsftpd*.conf
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
if [[ ! -z "${FTP_CHOWN_ROOT}" ]]; then
if [[ -n "${FTP_CHOWN_ROOT}" ]]; then
chown ftp:ftp /srv
fi

11
env.sample Normal file
View File

@@ -0,0 +1,11 @@
COMPOSE_PROJECT_NAME=vsftpd
VERSION=2.1
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
listen=YES
tcp_wrappers=YES
pasv_min_port=4559
pasv_max_port=4564
pasv_address=${FTP_PASV_ADDRESS}
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
listen=YES
tcp_wrappers=YES
pasv_min_port=4559
pasv_max_port=4564
pasv_address=${FTP_PASV_ADDRESS}
pasv_min_port=${FTP_PASV_MIN_PORT}
pasv_max_port=${FTP_PASV_MAX_PORT}
# SSL
ssl_enable=Yes