Automatic interactive installer for mtproto proxy https://github.com/seriyps/mtproto_proxy

April 3, 2026 · View on GitHub

#!/bin/bash

Automatic interactive installer for mtproto proxy https://github.com/seriyps/mtproto_proxy

Supported OS:

- Ubuntu 24.xx

- Ubuntu 23.xx

- Ubuntu 22.xx

- Debian 11 bullseye

RED='\033[0;31m' GR='\033[0;32m' YE='\033[0;33m' NC='\033[0m'

WORKDIR=pwd SRC_DIR=mtproto_proxy SELF="$0"

info() { echo -e "GRINFO{GR}INFO{NC}: $1" }

warn() { echo -e "YEWARNING{YE}WARNING{NC}: $1" }

error() { echo -e "REDERROR{RED}ERROR{NC}: $1" 1>&2 exit 1 }

usage() { echo "MTProto proxy installer. Install proxy: ${SELF} -p -s -t -a dd -a tls -d

Upgrade code to the latest version and restart, keeping config unchanged: ${SELF} upgrade

Interactively generate new config and reload proxy settings: ${SELF} reconfigure -p -s -t -a dd -a tls -d

Reload proxy settings after manual changes in config/prod-sys.cnfig: ${SELF} reload " }

to_hex() { od -A n -t x1 -w128 | sed 's/ //g' }

case "$1" in reconfigure|reload|upgrade|install) CMD="$1" shift ;; *) CMD="install" esac

PORT=MTPPORT:""SECRET={MTP_PORT:-""} SECRET={MTP_SECRET:-""} TAG=MTPTAG:""DDONLY={MTP_TAG:-""} DD_ONLY={MTP_DD_ONLY:-""} TLS_ONLY=MTPTLSONLY:""TLSDOMAIN={MTP_TLS_ONLY:-""} TLS_DOMAIN={MTP_TLS_DOMAIN:-""}

check command line options

while getopts "p:s:t:a:d:h" o; do case "o"inp)PORT={o}" in p) PORT={OPTARG} ;; s) SECRET=OPTARG;;t)TAG={OPTARG} ;; t) TAG={OPTARG} ;; a) case "OPTARG"in"dd")DDONLY="y";;"tls")TLSONLY="y";;)error"Invalidavalue:{OPTARG}" in "dd") DD_ONLY="y" ;; "tls") TLS_ONLY="y" ;; *) error "Invalid -a value: '{OPTARG}'" esac ;; d) TLS_DOMAIN=${OPTARG} ;; h) usage exit 0 esac done

echo "Interactive MTProto proxy installer." echo "You can make the process fully automated by calling this script as 'echo "y\ny\ny\ny\ny\ny" | $0'." echo "Try $0 -h for more options."

set -e

source /etc/os-release info "Detected OS is ID{ID} {VERSION_ID}"

do_configure_os() { # We need at least 'make' 'sed' 'diff' 'od' 'install' 'tar' 'base64' 'awk'

case "${ID}-${VERSION_ID}" in
    ubuntu-22.*|ubuntu-23.*|ubuntu-24.*|debian-11)
        info "Installing required APT packages"
        sudo apt update
        sudo apt install erlang-nox erlang-dev make sed diffutils tar
        ;;
    centos-7)
        info "Installing extra repositories"
        sudo yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm \
             wget \
             https://packages.erlang-solutions.com/erlang-solutions-1.0-1.noarch.rpm
        info "Installing required RPM packages"
        sudo yum install chrony erlang-compiler erlang-erts erlang-kernel erlang-stdlib erlang-syntax_tools \
             erlang-crypto erlang-inets erlang-sasl erlang-ssl
        ;;
    *)
        error "Your OS ${ID} ${VERSION_ID} is not supported!"
esac

info "Making sure clock synchronization is enabled"
if [ `systemctl is-active ntp` = "active" ]; then
    info "Replacing ntpd with systemd-timesyncd"
    systemctl disable ntp
    systemctl stop ntp
fi
sudo timedatectl set-ntp on
info "Current time: `date`"

}

do_get_source() { info "Downloading proxy source code" curl -L https://github.com/seriyps/mtproto_proxy/archive/master.tar.gz -o mtproto_proxy.tar.gz

info "Unpacking source code"
tar -xaf mtproto_proxy.tar.gz

mv -T --backup=t mtproto_proxy-master $SRC_DIR

case "${ID}-${VERSION_ID}" in
    ubuntu-22.*)
        info "Downgrade rebar3 to 3.23.0"
        curl -L -o $SRC_DIR/rebar3 https://github.com/erlang/rebar3/releases/download/3.23.0/rebar3
        chmod +x $SRC_DIR/rebar3
        ;;
    *)
        ;;
esac

}

cd mtproto_proxy/

do_build_config() { info "Interactively generating config-file"

# So, we ask for port/secret/ad_tag/protocols only if they are not specified via
# command-line or env vars

if [ -z "${PORT}" ]; then
    PORT=443
    read -p "Use default proxy port 443? [y/n] " yn
    case $yn in
        [Nn]*)
            read -p "Enter port number: 1-32000: " PORT
            ;;
        *)
            info "Using default port 443"
            ;;
    esac
fi

if [ "${ID}" = "centos" -a "`sudo firewall-cmd --state 2>&1`" = "running" ]; then
    read -p "Should I configure firewall?

'd' to disable firewall completely 'n' if you will setup firewall by yourself [y/n/d] " yn case ynin[Yy])info"Openingyn in [Yy]*) info "Opening {PORT} port" sudo firewall-cmd --zone=public --add-port=PORT/tcppermanentsudofirewallcmdreload;;[Dd])warning"Stoppingfirewalld"sudosystemctlstopfirewalldsudosystemctldisablefirewalld;;)warn"Pleasemakesureproxyport{PORT}/tcp --permanent sudo firewall-cmd --reload ;; [Dd]*) warning "Stopping firewalld" sudo systemctl stop firewalld sudo systemctl disable firewalld ;; *) warn "Please make sure proxy port {PORT} is open on firewall! Use smth like: firewall-cmd --zone=public --add-port=${PORT}/tcp --permanent firewall-cmd --reload" ;; esac fi

if [ -z "${SECRET}" ]; then
    SECRET=`head -c 16 /dev/urandom | to_hex`
    read -p "Use randomly generated secret '${SECRET}'? [y/n] " yn
    case $yn in
        [Nn]*)
            read -p "Enter your secret: 16 hex characters 0-9a-f: " SECRET
            ;;
        *)
            info "Using random secret ${SECRET}"
            ;;
    esac
fi

if [ -z "${TAG}" ]; then
    TAG="8b081275ec12abd306faeb2f13efbdcb"
    read -p "Use empty @MTProxybot AD TAG? Answer 'n' to set AD TAG [y/n] " yn
    case $yn in
        [Nn]*)
            read -p "Enter your ad tag from @MTProxybot: " TAG
            ;;
        *)
            info "Using no AD TAG"
    esac
fi

if [ -z "${DD_ONLY}" ]; then
    DD_ONLY="y"
    read -p "Enable dd-only mode? (recommended) [y/n] " yn
    case $yn in
        [Nn]*)
            DD_ONLY=""
            warn "dd-only mode disabled"
            ;;
        *)
            info "Using dd-only mode"
    esac
fi

if [ -z "${TLS_ONLY}" ]; then
    TLS_ONLY="y"
    read -p "Enable TLS-only mode? (recommended) [y/n] " yn
    case $yn in
        [Nn]*)
            TLS_ONLY=""
            warn "TLS-only mode disabled"
            ;;
        *)
            info "Using TLS-only mode"
    esac
fi

if [ -z "${TLS_DOMAIN}" -a \( -n "${TLS_ONLY}" -o -z "${DD_ONLY}" \) ]; then
    # If tls_domain is not set and fake-tls is enabled, ask for domain
    TLS_DOMAIN="s3.amazonaws.com"
    read -p "Use '${TLS_DOMAIN}' as domain name for fake-tls? Answer 'n' to change to another [y/n] " yn
    case $yn in
        [Nn]*)
            read -p "Enter domain name: " TLS_DOMAIN
            ;;
        *)
            ;;
    esac
    info "Using '${TLS_DOMAIN}' for fake-TLS SNI"
fi

PROTO_ARG=""
if [ -n "${DD_ONLY}" -a -n "${TLS_ONLY}" ]; then
    PROTO_ARG='{allowed_protocols, [mtp_fake_tls,mtp_secure]},'
elif [ -n "${DD_ONLY}" ]; then
    PROTO_ARG='{allowed_protocols, [mtp_secure]},'
elif [ -n "${TLS_ONLY}" ]; then
    PROTO_ARG='{allowed_protocols, [mtp_fake_tls]},'
fi

FRONTING_ARG=""
if [ -n "${TLS_DOMAIN}" ]; then
    FRONTING_ARG='{domain_fronting, "'${TLS_DOMAIN}':443"},'
fi

[ -z "${PORT}" -o -z "${SECRET}" -o -z "${TAG}" ] && \
    error "Not enough options: port='${PORT}' secret='${SECRET}' ad_tag='${TAG}'"

[ ${PORT} -gt 0 -a ${PORT} -lt 65535 ] || \
    error "Invalid port value: ${PORT}"

[ -n "`echo $SECRET | grep -x '[[:xdigit:]]\{32\}'`" ] || \
    error "Invalid secret. Should be 32 chars of 0-9 a-f"

[ -n "`echo $TAG | grep -x '[[:xdigit:]]\{32\}'`" ] || \
    error "Invalid tag. Should be 32 chars of 0-9 a-f"

[ -z "${TLS_DOMAIN}" -o -n "`echo $TLS_DOMAIN | grep -xE '^([0-9a-z_-]+\.)+[a-z]{2,6}$'`" ] || \
    error "Invalid TLS domain '${TLS_DOMAIN}'. Should be valid domain name!"

echo '

%% -- mode: erlang -- [ {mtproto_proxy, %% see src/mtproto_proxy.app.src for examples. [ '{PROTO_ARG}' '{FRONTING_ARG}' {ports, [#{name => mtp_handler_1, listen_ip => "0.0.0.0", port => 'PORT,secret=><<"{PORT}', secret => <<"'{SECRET}'">>, tag => <<"'${TAG}'">>} ]} ]},

%% Logging config {kernel, [{logger_level, info}, {logger, [{handler, default, logger_std_h, #{level => info, formatter => {logger_formatter, #{single_line => true}}, config => #{type => file, file => "/var/log/mtproto-proxy/application.log", max_no_bytes => 104857600, % 100MB max_no_files => 10, filesync_repeat_interval => no_repeat}}}, {handler, console, logger_std_h, #{level => critical, config => #{type => standard_io}}} ]}]}, {sasl, [{errlog_type, error}]} ].' >config/prod-sys.config

info "Config is generated with following properties:

port=PORTsecret={PORT} secret={SECRET} tag=TAGtlsonly={TAG} tls_only={TLS_ONLY} dd_only=DDONLYdomain={DD_ONLY} domain={TLS_DOMAIN}" }

do_backup_config() { cp SRCDIR/config/prodsys.configSRC_DIR/config/prod-sys.config WORKDIR/prod-sys.config.bak }

do_restore_config() { cp $WORKDIR/prod-sys.config.bak config/prod-sys.config }

do_reload_config() { sudo make update-sysconfig sudo systemctl reload mtproto-proxy }

do_build() { info "Generating Erlang interpreter options" make config/prod-vm.args

info "Compiling"
make

}

do_install() { # Try to stop proxy in case this script is run not for the first time sudo systemctl stop mtproto-proxy || true

info "Installing"
sudo make install

info "Starting"
sudo systemctl enable mtproto-proxy
sudo systemctl start mtproto-proxy

}

do_print_links() { info "Detecting IP address" IP=curl -s -4 -m 10 http://ipv4.seriyps.com || curl -s -4 -m 10 https://digitalresistance.dog/myIp info "Detected external IP is ${IP}"

URL_PREFIX="https://t.me/proxy?server=${IP}&port=${PORT}&secret="

ESCAPED_SECRET=$(echo -n $SECRET | sed 's/../\\x&/g') # bytes
ESCAPED_TLS_SECRET="\xee${ESCAPED_SECRET}"${TLS_DOMAIN}
BASE64_TLS_SECRET=`echo -ne $ESCAPED_TLS_SECRET | base64 -w 0 | tr '+/' '-_'`
HEX_TLS_SECRET=`echo -ne $ESCAPED_TLS_SECRET | to_hex`

info "Logs: /var/log/mtproto-proxy/application.log"
info "Secret: ${SECRET}"
info "Proxy links:

Normal: URLPREFIX{URL_PREFIX}{SECRET} Secure: URLPREFIXdd{URL_PREFIX}dd{SECRET} Fake-TLS hex: URLPREFIX{URL_PREFIX}{HEX_TLS_SECRET} Fake-TLS base64: URLPREFIX{URL_PREFIX}{BASE64_TLS_SECRET} " }

info "Executing $CMD"

case "CMD"in"install")doconfigureosdogetsourcecdCMD" in "install") do_configure_os do_get_source cd SRC_DIR/ do_build_config do_build do_install do_print_links info "Proxy is ready" ;; "reconfigure") cd SRCDIR/dobuildconfigdoreloadconfigdoprintlinksinfo"Configupdated";;"reload")cdSRC_DIR/ do_build_config do_reload_config do_print_links info "Config updated" ;; "reload") cd SRC_DIR/ do_reload_config info "Config updated" ;; "upgrade") do_backup_config do_get_source cd $SRC_DIR/ do_restore_config do_build do_install info "Code upgraded" esac