Compare commits
22 Commits
26f542354d
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
3f6d7c34d5
|
|||
|
76f62bafb1
|
|||
|
9c460b101e
|
|||
|
a4203ed149
|
|||
|
f799ffadb4
|
|||
|
7758e98bd3
|
|||
|
25eb14f93b
|
|||
|
f4c0042ab2
|
|||
|
6ed58a676f
|
|||
|
799895baa0
|
|||
|
dcf768fd21
|
|||
|
9137f439f1
|
|||
|
fade210106
|
|||
|
e1e1e1ee29
|
|||
|
8dcdd4a30a
|
|||
|
8289114ee6
|
|||
|
9fca459f93
|
|||
|
d5c00a0308
|
|||
|
08134aefa5
|
|||
|
e92da50d28
|
|||
|
5eaede5ca8
|
|||
|
83d15f9436
|
166
.drone.yml
166
.drone.yml
@@ -1,166 +0,0 @@
|
|||||||
kind: pipeline
|
|
||||||
type: docker
|
|
||||||
name: linux-amd64
|
|
||||||
|
|
||||||
platform:
|
|
||||||
arch: amd64
|
|
||||||
os: linux
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: build
|
|
||||||
image: plugins/docker:linux-amd64
|
|
||||||
settings:
|
|
||||||
dockerfile: Dockerfile
|
|
||||||
dry_run: true
|
|
||||||
repo: docker.asperti.com/paspo/ftps
|
|
||||||
when:
|
|
||||||
event:
|
|
||||||
- push
|
|
||||||
|
|
||||||
- name: build_and_publish
|
|
||||||
image: plugins/docker:linux-amd64
|
|
||||||
settings:
|
|
||||||
dockerfile: Dockerfile
|
|
||||||
force_tag: true
|
|
||||||
password:
|
|
||||||
from_secret: docker_password
|
|
||||||
registry: docker.asperti.com
|
|
||||||
repo: docker.asperti.com/paspo/ftps
|
|
||||||
username:
|
|
||||||
from_secret: docker_username
|
|
||||||
tags:
|
|
||||||
- ${DRONE_TAG}-linux-amd64
|
|
||||||
- ${DRONE_SEMVER_MAJOR}.${DRONE_SEMVER_MINOR}-linux-amd64
|
|
||||||
- ${DRONE_SEMVER_MAJOR}-linux-amd64
|
|
||||||
when:
|
|
||||||
event:
|
|
||||||
- tag
|
|
||||||
|
|
||||||
- name: build_and_publish2
|
|
||||||
image: plugins/docker:linux-amd64
|
|
||||||
settings:
|
|
||||||
dockerfile: Dockerfile
|
|
||||||
force_tag: true
|
|
||||||
password:
|
|
||||||
from_secret: gitea_docker_password
|
|
||||||
registry: git.asperti.com
|
|
||||||
repo: git.asperti.com/paspo/docker-ftps
|
|
||||||
username:
|
|
||||||
from_secret: gitea_docker_username
|
|
||||||
tags:
|
|
||||||
- ${DRONE_TAG}-linux-amd64
|
|
||||||
- ${DRONE_SEMVER_MAJOR}.${DRONE_SEMVER_MINOR}-linux-amd64
|
|
||||||
- ${DRONE_SEMVER_MAJOR}-linux-amd64
|
|
||||||
when:
|
|
||||||
event:
|
|
||||||
- tag
|
|
||||||
|
|
||||||
---
|
|
||||||
kind: pipeline
|
|
||||||
type: docker
|
|
||||||
name: linux-arm64
|
|
||||||
|
|
||||||
platform:
|
|
||||||
arch: arm64
|
|
||||||
os: linux
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: build
|
|
||||||
image: plugins/docker:linux-arm64
|
|
||||||
settings:
|
|
||||||
dockerfile: Dockerfile
|
|
||||||
dry_run: true
|
|
||||||
repo: docker.asperti.com/paspo/ftps
|
|
||||||
when:
|
|
||||||
event:
|
|
||||||
- push
|
|
||||||
|
|
||||||
- name: build_and_publish
|
|
||||||
image: plugins/docker:linux-arm64
|
|
||||||
settings:
|
|
||||||
dockerfile: Dockerfile
|
|
||||||
force_tag: true
|
|
||||||
password:
|
|
||||||
from_secret: docker_password
|
|
||||||
registry: docker.asperti.com
|
|
||||||
repo: docker.asperti.com/paspo/ftps
|
|
||||||
username:
|
|
||||||
from_secret: docker_username
|
|
||||||
tags:
|
|
||||||
- ${DRONE_TAG}-linux-arm64
|
|
||||||
- ${DRONE_SEMVER_MAJOR}.${DRONE_SEMVER_MINOR}-linux-arm64
|
|
||||||
- ${DRONE_SEMVER_MAJOR}-linux-arm64
|
|
||||||
when:
|
|
||||||
event:
|
|
||||||
- tag
|
|
||||||
|
|
||||||
- name: build_and_publish2
|
|
||||||
image: plugins/docker:linux-arm64
|
|
||||||
settings:
|
|
||||||
dockerfile: Dockerfile
|
|
||||||
force_tag: true
|
|
||||||
password:
|
|
||||||
from_secret: gitea_docker_password
|
|
||||||
registry: git.asperti.com
|
|
||||||
repo: git.asperti.com/paspo/docker-ftps
|
|
||||||
username:
|
|
||||||
from_secret: gitea_docker_username
|
|
||||||
tags:
|
|
||||||
- ${DRONE_TAG}-linux-arm64
|
|
||||||
- ${DRONE_SEMVER_MAJOR}.${DRONE_SEMVER_MINOR}-linux-arm64
|
|
||||||
- ${DRONE_SEMVER_MAJOR}-linux-arm64
|
|
||||||
when:
|
|
||||||
event:
|
|
||||||
- tag
|
|
||||||
|
|
||||||
---
|
|
||||||
kind: pipeline
|
|
||||||
type: docker
|
|
||||||
name: manifest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: manifest
|
|
||||||
image: plugins/manifest
|
|
||||||
settings:
|
|
||||||
force_tag: true
|
|
||||||
ignore_missing: true
|
|
||||||
spec: manifest.tmpl
|
|
||||||
username:
|
|
||||||
from_secret: docker_username
|
|
||||||
password:
|
|
||||||
from_secret: docker_password
|
|
||||||
tags:
|
|
||||||
- latest
|
|
||||||
- ${DRONE_TAG}
|
|
||||||
- ${DRONE_SEMVER_MAJOR}.${DRONE_SEMVER_MINOR}
|
|
||||||
- ${DRONE_SEMVER_MAJOR}
|
|
||||||
when:
|
|
||||||
event:
|
|
||||||
- tag
|
|
||||||
|
|
||||||
- name: manifest2
|
|
||||||
image: plugins/manifest
|
|
||||||
settings:
|
|
||||||
force_tag: true
|
|
||||||
ignore_missing: true
|
|
||||||
spec: manifest2.tmpl
|
|
||||||
username:
|
|
||||||
from_secret: gitea_docker_username
|
|
||||||
password:
|
|
||||||
from_secret: gitea_docker_password
|
|
||||||
tags:
|
|
||||||
- latest
|
|
||||||
- ${DRONE_TAG}
|
|
||||||
- ${DRONE_SEMVER_MAJOR}.${DRONE_SEMVER_MINOR}
|
|
||||||
- ${DRONE_SEMVER_MAJOR}
|
|
||||||
when:
|
|
||||||
event:
|
|
||||||
- tag
|
|
||||||
|
|
||||||
trigger:
|
|
||||||
event:
|
|
||||||
- tag
|
|
||||||
|
|
||||||
depends_on:
|
|
||||||
- linux-amd64
|
|
||||||
- linux-arm64
|
|
||||||
73
.gitea/workflows/build_and_publish.yaml
Normal file
73
.gitea/workflows/build_and_publish.yaml
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
---
|
||||||
|
name: Container Publish
|
||||||
|
|
||||||
|
env:
|
||||||
|
REGISTRY: docker.asperti.com
|
||||||
|
REPOSITORY: paspo/ftps
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
schedule:
|
||||||
|
- cron: "0 12 * * 3"
|
||||||
|
workflow_dispatch:
|
||||||
|
workflow_call:
|
||||||
|
workflow_run:
|
||||||
|
workflows: [vulnscan.yaml]
|
||||||
|
types: [completed]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
on-success-skip:
|
||||||
|
runs-on:
|
||||||
|
labels: ubuntu-latest
|
||||||
|
if: ${{ github.event.workflow_run.conclusion == 'success' }}
|
||||||
|
steps:
|
||||||
|
- run: exit_with_success
|
||||||
|
|
||||||
|
build-image:
|
||||||
|
runs-on:
|
||||||
|
labels: [ubuntu-latest, "arch-${{ matrix.arch }}"]
|
||||||
|
container:
|
||||||
|
image: catthehacker/ubuntu:act-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
arch: [amd64, arm64]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Login to registry
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ${{ env.REGISTRY }}
|
||||||
|
username: ${{ secrets.REGISTRY_USER }}
|
||||||
|
password: ${{ secrets.REGISTRY_TOKEN }}
|
||||||
|
|
||||||
|
- name: Build and publish
|
||||||
|
run: |
|
||||||
|
docker build \
|
||||||
|
--tag ${{ env.REGISTRY }}/${{ env.REPOSITORY }}:latest-${{ matrix.arch }} \
|
||||||
|
--platform linux/${{ matrix.arch }} --no-cache -f Dockerfile .
|
||||||
|
docker push ${{ env.REGISTRY }}/${{ env.REPOSITORY }}:latest-${{ matrix.arch }}
|
||||||
|
|
||||||
|
manifest:
|
||||||
|
name: update docker manifest
|
||||||
|
needs: build-image
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: catthehacker/ubuntu:act-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Login to registry
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ${{ env.REGISTRY }}
|
||||||
|
username: ${{ secrets.REGISTRY_USER }}
|
||||||
|
password: ${{ secrets.REGISTRY_TOKEN }}
|
||||||
|
|
||||||
|
- name: latest
|
||||||
|
run: |
|
||||||
|
docker manifest create \
|
||||||
|
${{ env.REGISTRY }}/${{ env.REPOSITORY }}:latest \
|
||||||
|
--amend ${{ env.REGISTRY }}/${{ env.REPOSITORY }}:latest-amd64 \
|
||||||
|
--amend ${{ env.REGISTRY }}/${{ env.REPOSITORY }}:latest-arm64
|
||||||
|
docker manifest push ${{ env.REGISTRY }}/${{ env.REPOSITORY }}:latest
|
||||||
64
.gitea/workflows/vulnscan.yaml
Normal file
64
.gitea/workflows/vulnscan.yaml
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
---
|
||||||
|
name: Vulnerability Scan
|
||||||
|
|
||||||
|
env:
|
||||||
|
REGISTRY: docker.asperti.com
|
||||||
|
REPOSITORY: paspo/ftps
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: "0 14 * * *"
|
||||||
|
workflow_dispatch:
|
||||||
|
workflow_call:
|
||||||
|
workflow_run:
|
||||||
|
workflows: [build_and_publish.yaml]
|
||||||
|
types: [completed]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
scan:
|
||||||
|
name: Daily Vulnerability Scan
|
||||||
|
runs-on:
|
||||||
|
labels: [ubuntu-latest, "arch-${{ matrix.arch }}"]
|
||||||
|
container:
|
||||||
|
image: catthehacker/ubuntu:act-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
arch: [amd64, arm64]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Pull docker image
|
||||||
|
run: docker pull ${{ env.REGISTRY }}/${{ env.REPOSITORY }}:latest
|
||||||
|
|
||||||
|
- name: Setup trivy
|
||||||
|
run: |
|
||||||
|
echo "Installing Trivy for arch: $(uname -m)"
|
||||||
|
case $(uname -m) in
|
||||||
|
x86_64)
|
||||||
|
wget -O /tmp/trivy.deb https://github.com/aquasecurity/trivy/releases/download/v0.58.2/trivy_0.58.2_Linux-64bit.deb ;;
|
||||||
|
aarch64)
|
||||||
|
wget -O /tmp/trivy.deb https://github.com/aquasecurity/trivy/releases/download/v0.58.2/trivy_0.58.2_Linux-ARM64.deb ;;
|
||||||
|
*) exit 1 ;;
|
||||||
|
esac
|
||||||
|
dpkg -i /tmp/trivy.deb
|
||||||
|
|
||||||
|
- name: Run Trivy vulnerability scanner
|
||||||
|
id: scan
|
||||||
|
run: |
|
||||||
|
trivy --server ${{ secrets.TRIVY_SERVER }} --token ${{ secrets.TRIVY_TOKEN }} image --format json ${{ env.REGISTRY }}/${{ env.REPOSITORY }}:latest > trivy-results.json
|
||||||
|
|
||||||
|
# if some vulnerability is found, we fail
|
||||||
|
- name: check output
|
||||||
|
id: vulncount
|
||||||
|
run: |
|
||||||
|
echo "VULNCOUNT=$(jq '.Results[0].Vulnerabilities|length' trivy-results.json)" >> ${GITHUB_OUTPUT}
|
||||||
|
if [ $(jq '.Results[0].Vulnerabilities|length' trivy-results.json) -ne "0" ] ; then exit 1 ; fi
|
||||||
|
|
||||||
|
- name: send telegram notification
|
||||||
|
if: failure()
|
||||||
|
uses: appleboy/telegram-action@master
|
||||||
|
with:
|
||||||
|
to: ${{ secrets.TELEGRAM_TO }}
|
||||||
|
token: ${{ secrets.TELEGRAM_TOKEN }}
|
||||||
|
format: markdown
|
||||||
|
message: |
|
||||||
|
Found **${{ steps.vulncount.outputs.VULNCOUNT }}** vulnerabilities in `${{ env.REGISTRY }}/${{ env.REPOSITORY }}:latest`
|
||||||
@@ -1,9 +1,15 @@
|
|||||||
FROM alpine:latest
|
FROM alpine:latest
|
||||||
|
|
||||||
RUN \
|
RUN \
|
||||||
apk -U add proftpd proftpd-mod_tls proftpd-mod_ifsession proftpd-utils openssl perl acme.sh && \
|
apk --no-cache upgrade && \
|
||||||
|
apk --no-cache add proftpd proftpd-mod_tls proftpd-mod_ifsession \
|
||||||
|
proftpd-mod_deflate proftpd-mod_geoip proftpd-mod_sql_sqlite \
|
||||||
|
proftpd-utils openssl perl acme.sh lftp sqlite && \
|
||||||
mkdir -p /var/run/proftpd /etc/proftpd/custom.conf.d/
|
mkdir -p /var/run/proftpd /etc/proftpd/custom.conf.d/
|
||||||
|
|
||||||
COPY rootfs /
|
COPY rootfs /
|
||||||
|
|
||||||
|
HEALTHCHECK --interval=2m --timeout=3s \
|
||||||
|
CMD /app/healthcheck.sh || exit 1
|
||||||
|
|
||||||
ENTRYPOINT ["/app/entrypoint.sh"]
|
ENTRYPOINT ["/app/entrypoint.sh"]
|
||||||
|
|||||||
52
README.md
52
README.md
@@ -144,3 +144,55 @@ docker exec -ti my-ftps ftpasswd --passwd --name=paolo --uid=1000 --home=/home/p
|
|||||||
```
|
```
|
||||||
|
|
||||||
You also have to create and chown the user's home folder.
|
You also have to create and chown the user's home folder.
|
||||||
|
|
||||||
|
## sql db for user authentication
|
||||||
|
|
||||||
|
It is possible to use a sqlite db for user authentication, just add `SQLITE_AUTH=1` to the environment:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
version: "3"
|
||||||
|
services:
|
||||||
|
ftps-server:
|
||||||
|
image: docker.asperti.com/paspo/ftps
|
||||||
|
restart: always
|
||||||
|
ports:
|
||||||
|
- "21:21"
|
||||||
|
- "20:20"
|
||||||
|
- "21210-21220:21210-21220"
|
||||||
|
volumes:
|
||||||
|
- "/srv/ftps/auth:/auth"
|
||||||
|
- "/srv/ftps/conf:/etc/proftpd/custom.conf.d:ro"
|
||||||
|
- "/srv/ftps/data:/home"
|
||||||
|
- "/etc/letsencrypt:/certs:ro"
|
||||||
|
environment:
|
||||||
|
- SQLITE_AUTH=1
|
||||||
|
- MASQUERADE=ftp.mydomain.com
|
||||||
|
- PASSIVEPORTS_START=21210
|
||||||
|
- PASSIVEPORTS_END=21220
|
||||||
|
- MAXCLIENTS=500
|
||||||
|
- MAXCLIENTSPERHOST=100
|
||||||
|
- TLS_CERT=/certs/live/ftp.mydomain.com/cert.pem
|
||||||
|
- TLS_KEY=/certs/live/ftp.mydomain.com/privkey.pem
|
||||||
|
- TLS_CHAIN=/certs/live/ftp.mydomain.com/chain.pem
|
||||||
|
```
|
||||||
|
|
||||||
|
Now, instead of using `/auth/passwd`, proftpd is using `/auth/ftpd.db`.
|
||||||
|
To create a new user, you must now update this db.
|
||||||
|
|
||||||
|
To create a new user:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker exec -ti my-ftps sqlite3 sqlite3 /auth/ftpd.db <<EOF
|
||||||
|
INSERT OR IGNORE INTO users (userid,passwd,uid,gid,homedir,shell) VALUES ('new_user','',1000,1000,'/home/new_user','/bin/false');
|
||||||
|
INSERT OR IGNORE INTO groups (groupname,gid,members) VALUES ('new_user',1000,'new_user');
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
|
||||||
|
To update a password:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
PASSWD_SHA=$(echo -n ChangeThisPass | mkpasswd -m sha512)
|
||||||
|
docker exec -ti my-ftps sqlite3 sqlite3 /auth/ftpd.db <<EOF
|
||||||
|
UPDATE users SET passwd='$PASSWD_SHA' WHERE userid='new_user';
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
image: docker.asperti.com/paspo/ftps:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}latest{{/if}}
|
|
||||||
{{#if build.tags}}
|
|
||||||
tags:
|
|
||||||
{{#each build.tags}}
|
|
||||||
- {{this}}
|
|
||||||
{{/each}}
|
|
||||||
{{/if}}
|
|
||||||
manifests:
|
|
||||||
-
|
|
||||||
image: docker.asperti.com/paspo/ftps:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-amd64
|
|
||||||
platform:
|
|
||||||
architecture: amd64
|
|
||||||
os: linux
|
|
||||||
-
|
|
||||||
image: docker.asperti.com/paspo/ftps:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm64
|
|
||||||
platform:
|
|
||||||
variant: v8
|
|
||||||
architecture: arm64
|
|
||||||
os: linux
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
image: git.asperti.com/paspo/docker-ftps:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}latest{{/if}}
|
|
||||||
{{#if build.tags}}
|
|
||||||
tags:
|
|
||||||
{{#each build.tags}}
|
|
||||||
- {{this}}
|
|
||||||
{{/each}}
|
|
||||||
{{/if}}
|
|
||||||
manifests:
|
|
||||||
-
|
|
||||||
image: git.asperti.com/paspo/docker-ftps:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-amd64
|
|
||||||
platform:
|
|
||||||
architecture: amd64
|
|
||||||
os: linux
|
|
||||||
-
|
|
||||||
image: git.asperti.com/paspo/docker-ftps:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm64
|
|
||||||
platform:
|
|
||||||
variant: v8
|
|
||||||
architecture: arm64
|
|
||||||
os: linux
|
|
||||||
@@ -23,6 +23,8 @@ if [ ! -f "/acme/cert/cert.pem" ] ; then
|
|||||||
--key-file /acme/cert/privkey.pem \
|
--key-file /acme/cert/privkey.pem \
|
||||||
--fullchain-file /acme/cert/chain.pem \
|
--fullchain-file /acme/cert/chain.pem \
|
||||||
--reloadcmd /app/acme-refresh-cert.sh ${ACME_EMAIL}
|
--reloadcmd /app/acme-refresh-cert.sh ${ACME_EMAIL}
|
||||||
|
echo "Certificate ready"
|
||||||
else
|
else
|
||||||
|
/app/acme-refresh-cert.sh
|
||||||
echo "Certificate ready"
|
echo "Certificate ready"
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -3,3 +3,6 @@
|
|||||||
if [ "$ENABLE_ACME" = "1" ] ; then
|
if [ "$ENABLE_ACME" = "1" ] ; then
|
||||||
/usr/bin/acme.sh --cron --home /acme
|
/usr/bin/acme.sh --cron --home /acme
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
############ RELOAD
|
||||||
|
pidof proftpd >/dev/null && killall -HUP proftpd
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ TLS_CHAIN=/acme/cert/chain.pem
|
|||||||
[ ! -f "$TLS_CHAIN" ] && exit 1
|
[ ! -f "$TLS_CHAIN" ] && exit 1
|
||||||
|
|
||||||
############ CHECK CERT KEY ALGO
|
############ CHECK CERT KEY ALGO
|
||||||
ALGO=$(openssl x509 -in "$TLS_CERT"-text | sed -n 's/\ *Public Key Algorithm: //p' | tr '\n')
|
ALGO=$(openssl x509 -in "$TLS_CERT" -text | sed -n 's/\ *Public Key Algorithm: //p' | tr '\n')
|
||||||
|
|
||||||
############ UPDATE cert config if needed
|
############ UPDATE cert config if needed
|
||||||
if [ "$ALGO" = "id-ecPublicKey" ] ; then
|
if [ "$ALGO" = "id-ecPublicKey" ] ; then
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
|
############ CREATE DIRS
|
||||||
|
mkdir -p /auth /logs
|
||||||
|
chown proftpd /auth /logs
|
||||||
|
chmod u+rw /auth /logs
|
||||||
|
chmod g-w /auth /logs
|
||||||
|
|
||||||
############ MASQUERADE
|
############ MASQUERADE
|
||||||
MASQUERADE=${MASQUERADE:-127.0.0.1}
|
MASQUERADE=${MASQUERADE:-127.0.0.1}
|
||||||
echo "MasqueradeAddress ${MASQUERADE}" > /etc/proftpd/conf.d/masquerade.conf
|
echo "MasqueradeAddress ${MASQUERADE}" > /etc/proftpd/conf.d/masquerade.conf
|
||||||
@@ -29,6 +35,42 @@ else
|
|||||||
/app/cert-init.sh
|
/app/cert-init.sh
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
############ INIT DB if needed
|
||||||
|
SQLITE_AUTH=${SQLITE_AUTH:-no}
|
||||||
|
if [ "$SQLITE_AUTH" = "1" ] ; then
|
||||||
|
if [ ! -f /auth/ftpd.db ] ; then
|
||||||
|
sqlite3 /auth/ftpd.db < /app/init.sql
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
############ GENERATE RANDOM PASSWORD FOR HEALTHCHECK
|
||||||
|
head /dev/urandom | tr -dc A-Za-z0-9 | head -c 20 > /app/healthcheck.pwd
|
||||||
|
chmod 600 /app/healthcheck.pwd
|
||||||
|
|
||||||
|
############ UPDATE HEALTHCHECK CREDS
|
||||||
|
HEALTHCHECK_UID=1999
|
||||||
|
mkdir -p /home/healthcheck
|
||||||
|
chown ${HEALTHCHECK_UID}:${HEALTHCHECK_UID} /home/healthcheck
|
||||||
|
if [ "$SQLITE_AUTH" = "1" ] ; then
|
||||||
|
PASSWD_SHA=$(cat /app/healthcheck.pwd | mkpasswd -m sha512)
|
||||||
|
sqlite3 /auth/ftpd.db <<EOF
|
||||||
|
INSERT OR IGNORE INTO users (userid,passwd,uid,gid,homedir,shell) VALUES ('healthcheck','',${HEALTHCHECK_UID},${HEALTHCHECK_UID},'/home/healthcheck','/bin/false');
|
||||||
|
INSERT OR IGNORE INTO groups (groupname,gid,members) VALUES ('healthcheck',${HEALTHCHECK_UID},'healthcheck');
|
||||||
|
UPDATE users SET passwd='$PASSWD_SHA' WHERE userid='healthcheck';
|
||||||
|
EOF
|
||||||
|
else
|
||||||
|
cat /app/healthcheck.pwd | ftpasswd --stdin --passwd --name=healthcheck \
|
||||||
|
--uid=${HEALTHCHECK_UID} \
|
||||||
|
--home=/home/healthcheck --sha512 --shell=/bin/false --file=/auth/passwd
|
||||||
|
fi
|
||||||
|
|
||||||
|
############ CONFIGURE AUTH
|
||||||
|
if [ "$SQLITE_AUTH" = "1" ] ; then
|
||||||
|
echo "AuthOrder mod_sql.c" > /etc/proftpd/conf.d/auth.conf
|
||||||
|
else
|
||||||
|
echo "AuthOrder mod_auth_file.c" > /etc/proftpd/conf.d/auth.conf
|
||||||
|
fi
|
||||||
|
|
||||||
############ START CRON
|
############ START CRON
|
||||||
crond -b
|
crond -b
|
||||||
|
|
||||||
|
|||||||
7
rootfs/app/healthcheck.sh
Executable file
7
rootfs/app/healthcheck.sh
Executable file
@@ -0,0 +1,7 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
USER=healthcheck
|
||||||
|
LFTP_PASSWORD=$(cat /app/healthcheck.pwd)
|
||||||
|
|
||||||
|
lftp -e "set ssl-allow true; set ftp:ssl-force true; set ftp:passive-mode true; set ssl:verify-certificate false; set net:timeout 5; set net:max-retries 1; open -u ${USER},${LFTP_PASSWORD} ftp://127.0.0.1; ls; bye" > /dev/null
|
||||||
|
echo $?
|
||||||
14
rootfs/app/init.sql
Normal file
14
rootfs/app/init.sql
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
CREATE TABLE `users` (
|
||||||
|
userid VARCHAR(30) NOT NULL UNIQUE,
|
||||||
|
passwd VARCHAR(80) NOT NULL,
|
||||||
|
uid INTEGER UNIQUE,
|
||||||
|
gid INTEGER,
|
||||||
|
homedir VARCHAR(255),
|
||||||
|
shell VARCHAR(255),
|
||||||
|
last_accessed DATETIME
|
||||||
|
);
|
||||||
|
CREATE TABLE `groups` (
|
||||||
|
groupname VARCHAR(30) NOT NULL UNIQUE,
|
||||||
|
gid INTEGER NOT NULL,
|
||||||
|
members VARCHAR(255)
|
||||||
|
);
|
||||||
@@ -11,7 +11,7 @@ TLS_CHAIN=/acme/cert/chain.pem
|
|||||||
[ ! -f "$TLS_CHAIN" ] && exit 1
|
[ ! -f "$TLS_CHAIN" ] && exit 1
|
||||||
|
|
||||||
############ CHECK CERT KEY ALGO
|
############ CHECK CERT KEY ALGO
|
||||||
ALGO=$(openssl x509 -in "$TLS_CERT"-text | sed -n 's/\ *Public Key Algorithm: //p' | tr '\n')
|
ALGO=$(openssl x509 -in "$TLS_CERT" -text | sed -n 's/\ *Public Key Algorithm: //p' | tr '\n')
|
||||||
|
|
||||||
############ UPDATE cert config if needed
|
############ UPDATE cert config if needed
|
||||||
if [ "$ALGO" = "id-ecPublicKey" ] ; then
|
if [ "$ALGO" = "id-ecPublicKey" ] ; then
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
AuthOrder mod_auth_file.c
|
|
||||||
AuthUserFile /auth/passwd
|
AuthUserFile /auth/passwd
|
||||||
RequireValidShell off
|
RequireValidShell off
|
||||||
ScoreBoardFile /run/proftpd/scoreboard
|
ScoreBoardFile /run/proftpd/scoreboard
|
||||||
@@ -23,4 +22,28 @@ DefaultRoot ~
|
|||||||
DelayTable /run/proftpd/proftpd.delay
|
DelayTable /run/proftpd/proftpd.delay
|
||||||
</IfModule>
|
</IfModule>
|
||||||
|
|
||||||
|
<IfModule mod_deflate.c>
|
||||||
|
DeflateEngine on
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
|
<IfModule mod_sql.c>
|
||||||
|
<IfModule mod_sql_sqlite.c>
|
||||||
|
SQLBackend sqlite3
|
||||||
|
SQLConnectInfo /auth/ftpd.db
|
||||||
|
SQLEngine On
|
||||||
|
SQLAuthenticate users
|
||||||
|
SQLAuthTypes OpenSSL Crypt
|
||||||
|
SQLUserInfo users userid passwd uid gid homedir shell
|
||||||
|
SQLGroupInfo groups groupname gid members
|
||||||
|
|
||||||
|
SQLNamedQuery last_accessed UPDATE "last_accessed = DATETIME('now') WHERE userid='%u'" users
|
||||||
|
SQLLog PASS last_accessed
|
||||||
|
SQLMinId 33
|
||||||
|
SQLDefaultUID 33
|
||||||
|
SQLDefaultGID 33
|
||||||
|
|
||||||
|
RequireValidShell off
|
||||||
|
</IfModule>
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
Include /etc/proftpd/custom.conf.d/
|
Include /etc/proftpd/custom.conf.d/
|
||||||
|
|||||||
56
rootfs/etc/proftpd/proftpd.conf
Normal file
56
rootfs/etc/proftpd/proftpd.conf
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
# This is the directory where DSO modules reside
|
||||||
|
ModulePath /usr/lib/proftpd
|
||||||
|
|
||||||
|
# Allow only user root to load and unload modules, but allow everyone
|
||||||
|
# to see which modules have been loaded
|
||||||
|
ModuleControlsACLs insmod,rmmod allow user root
|
||||||
|
ModuleControlsACLs lsmod allow user *
|
||||||
|
|
||||||
|
Include /etc/proftpd/modules.d/
|
||||||
|
|
||||||
|
ServerName "ProFTPD Default Installation"
|
||||||
|
ServerType standalone
|
||||||
|
|
||||||
|
# Port 21 is the standard FTP port.
|
||||||
|
Port 21
|
||||||
|
|
||||||
|
# Don't use IPv6 support by default.
|
||||||
|
UseIPv6 off
|
||||||
|
|
||||||
|
# Umask 022 is a good standard umask to prevent new dirs and files
|
||||||
|
# from being group and world writable.
|
||||||
|
Umask 022
|
||||||
|
|
||||||
|
# To prevent DoS attacks, set the maximum number of child processes
|
||||||
|
# to 30. If you need to allow more than 30 concurrent connections
|
||||||
|
# at once, simply increase this value. Note that this ONLY works
|
||||||
|
# in standalone mode, in inetd mode you should use an inetd server
|
||||||
|
# that allows you to limit maximum number of processes per service
|
||||||
|
# (such as xinetd).
|
||||||
|
MaxInstances 30
|
||||||
|
|
||||||
|
# Set the user and group under which the server will run.
|
||||||
|
User proftpd
|
||||||
|
Group proftpd
|
||||||
|
|
||||||
|
# To cause every FTP user to be "jailed" (chrooted) into their home
|
||||||
|
# directory, uncomment this line.
|
||||||
|
#DefaultRoot ~
|
||||||
|
|
||||||
|
# Normally, we want files to be overwriteable.
|
||||||
|
AllowOverwrite on
|
||||||
|
|
||||||
|
DefaultServer on
|
||||||
|
ShowSymlinks on
|
||||||
|
|
||||||
|
TimeoutNoTransfer 600
|
||||||
|
TimeoutStalled 600
|
||||||
|
TimeoutIdle 1200
|
||||||
|
|
||||||
|
DisplayLogin welcome.msg
|
||||||
|
DisplayChdir .message true
|
||||||
|
ListOptions "-l"
|
||||||
|
|
||||||
|
DenyFilter \*.*/
|
||||||
|
|
||||||
|
Include /etc/proftpd/conf.d/
|
||||||
4
rootfs/etc/shells
Normal file
4
rootfs/etc/shells
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
# valid login shells
|
||||||
|
/bin/sh
|
||||||
|
/bin/ash
|
||||||
|
/bin/false
|
||||||
Reference in New Issue
Block a user