mirror of
https://github.com/casjaysdevdocker/proftpd
synced 2026-11-08 09:22:27 -05:00
✨ Fix proftpd name, add TLS config and cert reload ✨
proftpd / release-proftpd (push) Failing after 1m9s
proftpd / release-proftpd (push) Failing after 1m9s
Rename proftp to proftpd, install proftpd with mod_tls, serve /var/ftp with a single config file, and reload proftpd when the cert changes. - .env.scripts: rename proftp to proftpd; SERVICE_PORT 21, EXPOSE_PORTS 49152-65534; add proftpd packages - Dockerfile: rename proftp to proftpd; port ARGs; PACK_LIST with proftpd, mod_tls, mod_readme, utils, openssl; labels from gen-dockerfile update - README.md: ports 21 and passive range; mounts for /var/ftp and /etc/letsencrypt - rootfs/.gitea/workflows/docker.yaml: rename proftp to proftpd - rootfs/tmp/etc/proftpd/proftpd.conf: single config, anonymous root /var/ftp, TLS 1.2/1.3 with certs at /etc/letsencrypt/live/domain, logs in /data/logs/proftpd - rootfs/usr/local/etc/docker/init.d/99-proftpd.sh: regenerate from current start-service template; add self-signed cert fallback, cert watcher that sends HUP on change, log dir chmod - rootfs/usr/local/etc/docker/functions/entrypoint.sh: use if blocks for debug echoes so set -e no longer exits the container when DEBUGGER is off - TODO.AI.md: log upstream template follow-ups (exit code 20, function-final [ ] && tails) - README.md: updated (ports and mounts for FTP and Let's Encrypt)
This commit is contained in:
8 files changed
+822
-377
No files matched your search
+11
-14
@@ -1,10 +1,10 @@
|
|||||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
##@Version : 202509161149-git
|
##@Version : 202611060818-git
|
||||||
# @@Author : CasjaysDev
|
# @@Author : CasjaysDev
|
||||||
# @@Contact : CasjaysDev <docker-admin@casjaysdev.pro>
|
# @@Contact : CasjaysDev <docker-admin@casjaysdev.pro>
|
||||||
# @@License : MIT
|
# @@License : WTFPL
|
||||||
# @@Copyright : Copyright 2025 CasjaysDev
|
# @@Copyright : Copyright 2026 CasjaysDev
|
||||||
# @@Created : Tue Sep 16 11:49:53 AM EDT 2025
|
# @@Created : Fri Nov 6 08:18:16 AM EST 2026
|
||||||
# @@File : .env.scripts
|
# @@File : .env.scripts
|
||||||
# @@Description : Variables for gen-dockerfile and buildx scripts
|
# @@Description : Variables for gen-dockerfile and buildx scripts
|
||||||
# @@Changelog : newScript
|
# @@Changelog : newScript
|
||||||
@@ -26,7 +26,7 @@ DOCKER_ENTYPOINT_HEALTH_ENDPOINTS="$DOCKER_ENTYPOINT_HEALTH_ENDPOINTS"
|
|||||||
# Dockerfile info
|
# Dockerfile info
|
||||||
ENV_DOCKERFILE="Dockerfile"
|
ENV_DOCKERFILE="Dockerfile"
|
||||||
# ENV_REGISTRY_REPO: Registry repository/image name
|
# ENV_REGISTRY_REPO: Registry repository/image name
|
||||||
ENV_REGISTRY_REPO="proftp"
|
ENV_REGISTRY_REPO="proftpd"
|
||||||
ENV_USE_TEMPLATE="alpine"
|
ENV_USE_TEMPLATE="alpine"
|
||||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
# Maintainer info
|
# Maintainer info
|
||||||
@@ -37,13 +37,13 @@ ENV_MAINTAINER="CasjaysDev <docker-admin@casjaysdev.pro>"
|
|||||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
# Repository URLs (Full URLs)
|
# Repository URLs (Full URLs)
|
||||||
# ENV_GIT_REPO_URL: Complete Git repository URL for source code
|
# ENV_GIT_REPO_URL: Complete Git repository URL for source code
|
||||||
ENV_GIT_REPO_URL="https://github.com/casjaysdevdocker/proftp"
|
ENV_GIT_REPO_URL="https://github.com/casjaysdevdocker/proftpd"
|
||||||
# ENV_REGISTRY_URL: Registry provider base URL (for example https://docker.io)
|
# ENV_REGISTRY_URL: Registry provider base URL (for example https://docker.io)
|
||||||
ENV_REGISTRY_URL="https://docker.io"
|
ENV_REGISTRY_URL="https://docker.io"
|
||||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
# Push Configuration
|
# Push Configuration
|
||||||
# ENV_REGISTRY_PUSH: Complete push destination derived from registry/org/repo
|
# ENV_REGISTRY_PUSH: Complete push destination derived from registry/org/repo
|
||||||
ENV_REGISTRY_PUSH="casjaysdevdocker/proftp"
|
ENV_REGISTRY_PUSH="casjaysdevdocker/proftpd"
|
||||||
# ENV_IMAGE_TAG: Default tag for the image
|
# ENV_IMAGE_TAG: Default tag for the image
|
||||||
ENV_IMAGE_TAG="latest"
|
ENV_IMAGE_TAG="latest"
|
||||||
# ENV_ADD_TAGS: Additional tags, comma-separated (USE_DATE = auto date tag)
|
# ENV_ADD_TAGS: Additional tags, comma-separated (USE_DATE = auto date tag)
|
||||||
@@ -59,8 +59,8 @@ ENV_PULL_URL="casjaysdev/alpine"
|
|||||||
ENV_DISTRO_TAG="${IMAGE_VERSION}"
|
ENV_DISTRO_TAG="${IMAGE_VERSION}"
|
||||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
# Env
|
# Env
|
||||||
SERVICE_PORT=""
|
SERVICE_PORT="21"
|
||||||
EXPOSE_PORTS=""
|
EXPOSE_PORTS="49152-65534"
|
||||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
# IF using a lanuage such as go, php, rust, ruby, etc set the version here.
|
# IF using a lanuage such as go, php, rust, ruby, etc set the version here.
|
||||||
LANG_VERSION=""
|
LANG_VERSION=""
|
||||||
@@ -72,12 +72,9 @@ NODE_MANAGER="system"
|
|||||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
# Default directories
|
# Default directories
|
||||||
WWW_ROOT_DIR="/usr/local/share/httpd/default"
|
WWW_ROOT_DIR="/usr/local/share/httpd/default"
|
||||||
DEFAULT_FILE_DIR="/usr/local/share/template-files"
|
|
||||||
DEFAULT_DATA_DIR="/usr/local/share/template-files/data"
|
|
||||||
DEFAULT_CONF_DIR="/usr/local/share/template-files/config"
|
|
||||||
DEFAULT_TEMPLATE_DIR="/usr/local/share/template-files/defaults"
|
|
||||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
ENV_PACKAGES=""
|
ENV_PACKAGES="proftpd proftpd-mod_tls proftpd-mod_readme proftpd-utils openssl"
|
||||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
# ex: ts=2 sw=2 et filetype=sh
|
# ex: ts=2 sw=2 et filetype=sh
|
||||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
||||||
+10
-10
@@ -1,6 +1,6 @@
|
|||||||
# Docker image for proftp using the alpine template
|
# Docker image for proftpd using the alpine template
|
||||||
ARG IMAGE_NAME="proftp"
|
ARG IMAGE_NAME="proftpd"
|
||||||
ARG PHP_SERVER="proftp"
|
ARG PHP_SERVER="proftpd"
|
||||||
ARG BUILD_DATE="202509161149"
|
ARG BUILD_DATE="202509161149"
|
||||||
ARG LANGUAGE="en_US.UTF-8"
|
ARG LANGUAGE="en_US.UTF-8"
|
||||||
ARG TIMEZONE="America/New_York"
|
ARG TIMEZONE="America/New_York"
|
||||||
@@ -14,13 +14,13 @@ ARG PATH="/usr/local/etc/docker/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/us
|
|||||||
ARG USER="root"
|
ARG USER="root"
|
||||||
ARG SHELL_OPTS="set -e -o pipefail"
|
ARG SHELL_OPTS="set -e -o pipefail"
|
||||||
|
|
||||||
ARG SERVICE_PORT=""
|
ARG SERVICE_PORT="21"
|
||||||
ARG EXPOSE_PORTS=""
|
ARG EXPOSE_PORTS="49152-65534"
|
||||||
ARG PHP_VERSION="system"
|
ARG PHP_VERSION="system"
|
||||||
ARG NODE_VERSION="system"
|
ARG NODE_VERSION="system"
|
||||||
ARG NODE_MANAGER="system"
|
ARG NODE_MANAGER="system"
|
||||||
|
|
||||||
ARG IMAGE_REPO="casjaysdevdocker/proftp"
|
ARG IMAGE_REPO="casjaysdevdocker/proftpd"
|
||||||
ARG IMAGE_VERSION="latest"
|
ARG IMAGE_VERSION="latest"
|
||||||
ARG CONTAINER_VERSION=""
|
ARG CONTAINER_VERSION=""
|
||||||
|
|
||||||
@@ -54,7 +54,7 @@ ARG PHP_SERVER
|
|||||||
ARG SHELL_OPTS
|
ARG SHELL_OPTS
|
||||||
ARG PATH
|
ARG PATH
|
||||||
|
|
||||||
ARG PACK_LIST=" "
|
ARG PACK_LIST="proftpd proftpd-mod_tls proftpd-mod_readme proftpd-utils openssl "
|
||||||
|
|
||||||
ENV ENV=~/.profile
|
ENV ENV=~/.profile
|
||||||
ENV SHELL="/bin/sh"
|
ENV SHELL="/bin/sh"
|
||||||
@@ -63,7 +63,7 @@ ENV TZ="${TIMEZONE}"
|
|||||||
ENV TIMEZONE="${TZ}"
|
ENV TIMEZONE="${TZ}"
|
||||||
ENV LANG="${LANGUAGE}"
|
ENV LANG="${LANGUAGE}"
|
||||||
ENV TERM="xterm-256color"
|
ENV TERM="xterm-256color"
|
||||||
ENV HOSTNAME="casjaysdevdocker-proftp"
|
ENV HOSTNAME="casjaysdevdocker-proftpd"
|
||||||
|
|
||||||
USER ${USER}
|
USER ${USER}
|
||||||
WORKDIR /root
|
WORKDIR /root
|
||||||
@@ -230,8 +230,8 @@ LABEL org.opencontainers.image.authors="${LICENSE}"
|
|||||||
LABEL org.opencontainers.image.created="${BUILD_DATE}"
|
LABEL org.opencontainers.image.created="${BUILD_DATE}"
|
||||||
LABEL org.opencontainers.image.version="${BUILD_VERSION}"
|
LABEL org.opencontainers.image.version="${BUILD_VERSION}"
|
||||||
LABEL org.opencontainers.image.schema-version="${BUILD_VERSION}"
|
LABEL org.opencontainers.image.schema-version="${BUILD_VERSION}"
|
||||||
LABEL org.opencontainers.image.url="https://docker.io/casjaysdevdocker/proftpd"
|
LABEL org.opencontainers.image.url="https://hub.docker.com/r/casjaysdevdocker/proftpd"
|
||||||
LABEL org.opencontainers.image.source="https://docker.io/casjaysdevdocker/proftpd"
|
LABEL org.opencontainers.image.source="https://github.com/casjaysdevdocker/proftpd"
|
||||||
LABEL org.opencontainers.image.vcs-type="Git"
|
LABEL org.opencontainers.image.vcs-type="Git"
|
||||||
LABEL org.opencontainers.image.revision="${GIT_COMMIT}"
|
LABEL org.opencontainers.image.revision="${GIT_COMMIT}"
|
||||||
LABEL org.opencontainers.image.source="https://github.com/casjaysdevdocker/proftpd"
|
LABEL org.opencontainers.image.source="https://github.com/casjaysdevdocker/proftpd"
|
||||||
|
|||||||
@@ -31,7 +31,10 @@ docker run -d \
|
|||||||
-e TZ=${TIMEZONE:-America/New_York} \
|
-e TZ=${TIMEZONE:-America/New_York} \
|
||||||
-v "$dockerHome/data:/data:z" \
|
-v "$dockerHome/data:/data:z" \
|
||||||
-v "$dockerHome/config:/config:z" \
|
-v "$dockerHome/config:/config:z" \
|
||||||
-p 80:80 \
|
-v "/srv/ftp:/var/ftp:z" \
|
||||||
|
-v "/etc/letsencrypt:/etc/letsencrypt:ro" \
|
||||||
|
-p 21:21 \
|
||||||
|
-p 49152-65534:49152-65534 \
|
||||||
casjaysdevdocker/proftpd:latest
|
casjaysdevdocker/proftpd:latest
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -49,8 +52,11 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- "/srv/$USER/docker/casjaysdevdocker/proftpd/proftpd/latest/rootfs/data:/data:z"
|
- "/srv/$USER/docker/casjaysdevdocker/proftpd/proftpd/latest/rootfs/data:/data:z"
|
||||||
- "/srv/$USER/docker/casjaysdevdocker/proftpd/proftpd/latest/rootfs/config:/config:z"
|
- "/srv/$USER/docker/casjaysdevdocker/proftpd/proftpd/latest/rootfs/config:/config:z"
|
||||||
|
- "/srv/ftp:/var/ftp:z"
|
||||||
|
- "/etc/letsencrypt:/etc/letsencrypt:ro"
|
||||||
ports:
|
ports:
|
||||||
- 80:80
|
- 21:21
|
||||||
|
- 49152-65534:49152-65534
|
||||||
restart: always
|
restart: always
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
- Upstream gen-script `other/start-service` template: `__run_pre_execute_checks ... || return 20` uses exit code 20, outside standard ranges; change to a sysexits code in the template, then regenerate rootfs/usr/local/etc/docker/init.d/99-proftpd.sh
|
||||||
|
- Upstream functions/entrypoint.sh template: function-final `[ "$DEBUGGER" = "on" ] && ...` lines return 1 under set -e (fixed locally in __symlink and the msmtp/ssmtp/postfix setup); fix in the template and audit remaining `[ ] && cmd` tails
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
name: proftp
|
name: proftpd
|
||||||
|
|
||||||
on: push
|
on: push
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
release-proftp:
|
release-proftpd:
|
||||||
runs-on: act_runner
|
runs-on: act_runner
|
||||||
container:
|
container:
|
||||||
image: catthehacker/ubuntu:act-latest
|
image: catthehacker/ubuntu:act-latest
|
||||||
|
|||||||
@@ -1,27 +1,53 @@
|
|||||||
# proftpd config
|
# ProFTPD configuration - single file: server, anonymous FTP and TLS
|
||||||
|
ModulePath /usr/lib/proftpd
|
||||||
|
LoadModule mod_tls.c
|
||||||
|
LoadModule mod_readme.c
|
||||||
|
ServerName ProFTPD
|
||||||
|
ServerAdmin root@localhost
|
||||||
|
DefaultServer on
|
||||||
|
PidFile /run/proftpd/proftpd.pid
|
||||||
|
DefaultRoot ~
|
||||||
|
AuthOrder mod_auth_unix.c
|
||||||
|
PersistentPasswd off
|
||||||
|
UseReverseDNS off
|
||||||
|
User ftp
|
||||||
|
Group ftp
|
||||||
|
MaxInstances 20
|
||||||
|
UseSendfile off
|
||||||
|
AllowForeignAddress on
|
||||||
|
AllowRetrieveRestart on
|
||||||
|
AllowStoreRestart on
|
||||||
|
DeferWelcome on
|
||||||
|
RootLogin off
|
||||||
|
RequireValidShell off
|
||||||
|
PassivePorts 49152 65534
|
||||||
|
SystemLog /data/logs/proftpd/error.log
|
||||||
|
LogFormat default "%h %l %u %t \"%r\" %s %b"
|
||||||
|
LogFormat auth "%v [%P] %h %t \"%r\" %s"
|
||||||
|
|
||||||
<Global>
|
<Global>
|
||||||
Umask 022
|
Umask 022
|
||||||
AllowOverwrite yes
|
AllowOverwrite yes
|
||||||
TransferLog /dev/stdout
|
TransferLog /data/logs/proftpd/xfers.log
|
||||||
ExtendedLog /dev/stdout
|
ExtendedLog /data/logs/proftpd/proftpd.log
|
||||||
DefaultRoot /data/ftp
|
DefaultRoot ~
|
||||||
DisplayConnect "/etc/motd"
|
DisplayConnect "/etc/motd"
|
||||||
</Global>
|
</Global>
|
||||||
|
|
||||||
<Anonymous /data/ftp>
|
<Anonymous /var/ftp>
|
||||||
User root
|
User ftp
|
||||||
Group root
|
Group ftp
|
||||||
AccessGrantMsg "Anonymous login ok, restrictions apply."
|
AccessGrantMsg "Anonymous login ok, restrictions apply."
|
||||||
UserAlias anonymous ftp
|
UserAlias anonymous ftp
|
||||||
MaxClients 2000 "Sorry, max %m users -- try again later"
|
MaxClients 20 "Sorry, max %m users -- try again later"
|
||||||
DisplayLogin /data/welcome.msg
|
DisplayLogin /var/ftp/welcome.msg
|
||||||
DisplayChdir .message
|
DisplayChdir .message
|
||||||
DisplayReadme README*
|
DisplayReadme README*
|
||||||
DirFakeUser on ftp
|
DirFakeUser on ftp
|
||||||
DirFakeGroup on ftp
|
DirFakeGroup on ftp
|
||||||
WtmpLog off
|
WtmpLog off
|
||||||
ExtendedLog /dev/stdout WRITE,READ default
|
ExtendedLog /data/logs/proftpd/access.log WRITE,READ default
|
||||||
ExtendedLog /dev/stdout AUTH auth
|
ExtendedLog /data/logs/proftpd/auth.log AUTH auth
|
||||||
AllowRetrieveRestart on
|
AllowRetrieveRestart on
|
||||||
AnonRequirePassword off
|
AnonRequirePassword off
|
||||||
<Limit WRITE>
|
<Limit WRITE>
|
||||||
@@ -29,15 +55,15 @@ AnonRequirePassword off
|
|||||||
</Limit>
|
</Limit>
|
||||||
</Anonymous>
|
</Anonymous>
|
||||||
|
|
||||||
PassivePorts 49152 65534
|
# TLS - certs at the literal letsencrypt "domain" dir; a self-signed pair is created if missing
|
||||||
|
<IfModule mod_tls.c>
|
||||||
TLSEngine on
|
TLSEngine on
|
||||||
TLSRequired off
|
TLSRequired off
|
||||||
TLSProtocol TLSv1 TLSv1.1 TLSv1.2
|
TLSProtocol TLSv1.2 TLSv1.3
|
||||||
TLSOptions NoSessionReuseRequired
|
TLSOptions NoSessionReuseRequired
|
||||||
TLSVerifyClient off
|
TLSVerifyClient off
|
||||||
TLSRenegotiate none
|
TLSRenegotiate none
|
||||||
TLSLog /dev/stdout
|
TLSLog /data/logs/proftpd/tls.log
|
||||||
|
TLSRSACertificateFile /etc/letsencrypt/live/domain/fullchain.pem
|
||||||
TLSCACertificateFile /config/ssl/ca.crt
|
TLSRSACertificateKeyFile /etc/letsencrypt/live/domain/privkey.pem
|
||||||
TLSRSACertificateFile /config/ssl/localhost.crt
|
</IfModule>
|
||||||
TLSRSACertificateKeyFile /config/ssl/localhost.key
|
|
||||||
@@ -645,7 +645,7 @@ __symlink() {
|
|||||||
[ "$from" = "$to" ] && return 0
|
[ "$from" = "$to" ] && return 0
|
||||||
__rm "$from"
|
__rm "$from"
|
||||||
[ -d "${from%/*}" ] || mkdir -p "${from%/*}" 2>/dev/null
|
[ -d "${from%/*}" ] || mkdir -p "${from%/*}" 2>/dev/null
|
||||||
ln -sf "$to" "$from" && [ "$DEBUGGER" = "on" ] && echo "Created symlink: $from -> $to"
|
ln -sf "$to" "$from" && if [ "$DEBUGGER" = "on" ]; then echo "Created symlink: $from -> $to"; fi
|
||||||
}
|
}
|
||||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
__file_copy() {
|
__file_copy() {
|
||||||
@@ -1180,7 +1180,7 @@ EOF
|
|||||||
if [ ! -e "/usr/sbin/sendmail" ] && command -v msmtp &>/dev/null; then
|
if [ ! -e "/usr/sbin/sendmail" ] && command -v msmtp &>/dev/null; then
|
||||||
__symlink "/usr/sbin/sendmail" "$(command -v msmtp)"
|
__symlink "/usr/sbin/sendmail" "$(command -v msmtp)"
|
||||||
fi
|
fi
|
||||||
[ "$DEBUGGER" = "on" ] && echo "Done setting up msmtp"
|
if [ "$DEBUGGER" = "on" ]; then echo "Done setting up msmtp"; fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
################# sSMTP relay setup
|
################# sSMTP relay setup
|
||||||
@@ -1221,7 +1221,7 @@ EOF
|
|||||||
__symlink "/etc/ssmtp/revaliases" "/config/ssmtp/revaliases"
|
__symlink "/etc/ssmtp/revaliases" "/config/ssmtp/revaliases"
|
||||||
__initialize_replace_variables "/etc/ssmtp/revaliases"
|
__initialize_replace_variables "/etc/ssmtp/revaliases"
|
||||||
fi
|
fi
|
||||||
[ "$DEBUGGER" = "on" ] && echo "Done setting up ssmtp"
|
if [ "$DEBUGGER" = "on" ]; then echo "Done setting up ssmtp"; fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
################# postfix relay setup
|
################# postfix relay setup
|
||||||
@@ -1275,7 +1275,7 @@ EOF
|
|||||||
if [ ! -f "/run/init.d/postfix.pid" ]; then
|
if [ ! -f "/run/init.d/postfix.pid" ]; then
|
||||||
__exec_service postfix start
|
__exec_service postfix start
|
||||||
fi
|
fi
|
||||||
[ "$DEBUGGER" = "on" ] && echo "Done setting up postfix"
|
if [ "$DEBUGGER" = "on" ]; then echo "Done setting up postfix"; fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
[ -f "/root/dead.letter" ] && __rm "/root/dead.letter"
|
[ -f "/root/dead.letter" ] && __rm "/root/dead.letter"
|
||||||
|
|||||||
Regular → Executable
+741
-327
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user