diff --git a/setup/start/proftpd.conf b/setup/start/proftpd.conf
new file mode 100644
index 000000000..f75bd1cba
--- /dev/null
+++ b/setup/start/proftpd.conf
@@ -0,0 +1,129 @@
+# Includes DSO modules
+Include /etc/proftpd/modules.conf
+
+# Set off to disable IPv6 support which is annoying on IPv4 only boxes.
+UseIPv6 off
+# If set on you can experience a longer connection delay in many cases.
+IdentLookups off
+
+ServerName "##SERVER_NAME"
+ServerType standalone
+DeferWelcome off
+
+MultilineRFC2228 on
+DefaultServer on
+ShowSymlinks on
+
+TimeoutNoTransfer 600
+TimeoutStalled 600
+TimeoutIdle 1200
+
+DisplayLogin welcome.msg
+DisplayChdir .message true
+ListOptions "-l"
+
+DenyFilter \*.*/
+
+# Use this to jail all users in their homes
+# DefaultRoot ~
+
+# Users require a valid shell listed in /etc/shells to login.
+# Use this directive to release that constrain.
+# RequireValidShell off
+
+# Port 21 is the standard FTP port.
+Port 0
+
+# 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 10
+
+# Set the user and group that the server normally runs at.
+User www-data
+Group www-data
+
+# Umask 022 is a good standard umask to prevent new files and dirs
+# (second parm) from being group and world writable.
+Umask 022 022
+# Normally, we want files to be overwriteable.
+AllowOverwrite on
+
+TransferLog /run/proftpd/xferlog
+SystemLog /run/proftpd/proftpd.log
+
+# disable ssh login log
+WtmpLog off
+
+
+QuotaEngine off
+
+
+
+Ratios off
+
+
+# Delay engine reduces impact of the so-called Timing Attack described in
+# http://www.securityfocus.com/bid/11430/discuss
+# It is on by default.
+
+DelayEngine on
+
+
+
+ControlsEngine off
+ControlsMaxClients 2
+ControlsLog /var/log/proftpd/controls.log
+ControlsInterval 5
+ControlsSocket /var/run/proftpd/proftpd.sock
+
+
+
+ AdminControlsEngine off
+
+
+LoadModule mod_ldap.c
+
+# https://forums.proftpd.org/smf/index.php?topic=6368.0
+LDAPServer "##LDAP_URL/??sub"
+LDAPBindDN "##LDAP_BIND_DN" "##LDAP_BIND_PASSWORD"
+LDAPUsers "##LDAP_USERS_BASE_DN" (username=%u)
+
+LDAPForceDefaultUID on
+LDAPDefaultUID ##LDAP_UID
+LDAPForceDefaultGID on
+LDAPDefaultGID ##LDAP_GID
+
+LDAPForceGeneratedHomedir on
+LDAPGenerateHomedir on
+LDAPGenerateHomedirPrefix /app/data
+LDAPGenerateHomedirPrefixNoUsername on
+
+#LDAPUseTLS off
+#LDAPLog /run/proftpd/ldap.log
+
+
+
+SFTPEngine on
+Port ##SFTP_PORT
+SFTPLog /run/proftpd/sftp.log
+
+# Configure both the RSA and DSA host keys, using the same host key
+# files that OpenSSH uses.
+SFTPHostKey /app/data/.sftpd/ssh_host_rsa_key
+SFTPHostKey /app/data/.sftpd/ssh_host_dsa_key
+
+SFTPAuthMethods password
+
+# Enable compression
+SFTPCompression delayed
+
+RequireValidShell off
+
+
+
+ HideNoAccess yes
+
diff --git a/setup/start/sudoers b/setup/start/sudoers
index 4c3d1d953..84c220a1b 100644
--- a/setup/start/sudoers
+++ b/setup/start/sudoers
@@ -49,3 +49,6 @@ yellowtent ALL=(root) NOPASSWD: /home/yellowtent/box/src/scripts/restartdocker.s
Defaults!/home/yellowtent/box/src/scripts/restartunbound.sh env_keep="HOME BOX_ENV"
yellowtent ALL=(root) NOPASSWD: /home/yellowtent/box/src/scripts/restartunbound.sh
+
+Defaults!/home/yellowtent/box/src/scripts/restartproftpd.sh env_keep="HOME BOX_ENV"
+yellowtent ALL=(root) NOPASSWD: /home/yellowtent/box/src/scripts/restartproftpd.sh
diff --git a/src/addons.js b/src/addons.js
index 56d75b44c..865319556 100644
--- a/src/addons.js
+++ b/src/addons.js
@@ -211,6 +211,11 @@ const KNOWN_SERVICES = {
status: statusUnbound,
restart: restartUnbound,
defaultMemoryLimit: 0
+ },
+ proftpd: {
+ status: statusProftpd,
+ restart: restartProftpd,
+ defaultMemoryLimit: 0
}
};
@@ -1715,3 +1720,19 @@ function restartUnbound(callback) {
callback(null);
}
+
+function statusProftpd(callback) {
+ assert.strictEqual(typeof callback, 'function');
+
+ shell.exec('statusProftpd', 'systemctl is-active proftpd', function (error) {
+ callback(null, { status: error ? exports.SERVICE_STATUS_STOPPED : exports.SERVICE_STATUS_ACTIVE });
+ });
+}
+
+function restartProftpd(callback) {
+ assert.strictEqual(typeof callback, 'function');
+
+ shell.sudo('restartProftpd', [ path.join(__dirname, 'scripts/restartproftpd.sh') ], {}, NOOP_CALLBACK);
+
+ callback(null);
+}
diff --git a/src/scripts/restartproftpd.sh b/src/scripts/restartproftpd.sh
new file mode 100755
index 000000000..b343cbdc5
--- /dev/null
+++ b/src/scripts/restartproftpd.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+
+set -eu -o pipefail
+
+if [[ ${EUID} -ne 0 ]]; then
+ echo "This script should be run as root." > /dev/stderr
+ exit 1
+fi
+
+if [[ $# == 1 && "$1" == "--check" ]]; then
+ echo "OK"
+ exit 0
+fi
+
+if [[ "${BOX_ENV}" == "cloudron" ]]; then
+ systemctl restart proftpd
+fi
+
diff --git a/src/test/checkInstall b/src/test/checkInstall
index 5518de3d7..4ea11f0b0 100755
--- a/src/test/checkInstall
+++ b/src/test/checkInstall
@@ -18,6 +18,7 @@ scripts=("${SOURCE_DIR}/src/scripts/clearvolume.sh" \
"${SOURCE_DIR}/src/scripts/restart.sh" \
"${SOURCE_DIR}/src/scripts/restartdocker.sh" \
"${SOURCE_DIR}/src/scripts/restartunbound.sh" \
+ "${SOURCE_DIR}/src/scripts/restartproftpd.sh" \
"${SOURCE_DIR}/src/scripts/update.sh" \
"${SOURCE_DIR}/src/scripts/collectlogs.sh" \
"${SOURCE_DIR}/src/scripts/configurecollectd.sh" \