Your own proxy server on a VPS: 3proxy install and checks
A step-by-step beginner guide: install 3proxy on a VPS with a ready bash script, test access from outside, connect a browser. And when you do not need it.

You can set up a personal proxy server even if you have never opened a Linux console: the installer itself takes a minute. Below is a step-by-step guide: rent a VPS, run a ready script, test access from outside and connect a browser. The result is one permanent IP with HTTP and SOCKS5 behind a login and password.
At the end of the article we will cover the tasks where a personal server loses to a service. We sell proxies ourselves, so we say this openly.
What you need
| What | Which |
|---|---|
| Server | VPS with 1 core and 512 MB of memory: the smallest plan is enough for a personal proxy |
| System | clean Ubuntu 22.04 or 24.04, Debian 12 or 13 |
| Access | root user and the password from the host's email |
| Terminal | PowerShell in Windows 10 and 11, Terminal in macOS and Linux |
Choose the VPS country for your task right away: the proxy address will be from that country, and you can change it only by moving to another server.
We ran all commands from this article on clean images of the four systems from the table, giving each 512 MB of memory and one core. Installation took from 10 to 31 seconds, and 3proxy itself took under 8 MB with no load.
We will install 3proxy. One program serves both HTTP and SOCKS5, uses little memory and is configured with one file. Squid works only as an HTTP proxy and Dante only as SOCKS, so with them you would have to configure two services. Ubuntu's repositories have no 3proxy package, so the script takes the developer's official package and verifies its checksum.
Step 1. Connect to the server
Open a terminal and enter the command, using the address from the host's email:
ssh root@SERVER_IPOn first login the system asks whether to trust the server: type yes. The password does not show as you type, and that is by design. Type it blind or paste it and press Enter. If the host gave you a regular user instead of root, run sudo -i after logging in.
Step 2. Run the installer
Press Copy, paste the whole block into the terminal window and press Enter. It creates the file and runs it by itself.
cat > install-proxy.sh <<'SCRIPT'
#!/usr/bin/env bash
# Installs 3proxy with HTTP and SOCKS5, login and password required.
# Ubuntu 22.04+ or Debian 12+. Run as root on a clean server.
set -euo pipefail
VERSION="1.0.2"
CONF_DIR="/usr/local/3proxy/conf"
if [ "$(id -u)" -ne 0 ]; then
echo "Run as root: sudo bash install-proxy.sh"
exit 1
fi
case "$(dpkg --print-architecture)" in
amd64) ARCH="x86_64"; SHA="d42c0a15ab7bc2e129de2e72fedfb6c908bfc1f7b7f4be15368c56eeb21e9a08" ;;
arm64) ARCH="arm64"; SHA="e7b8f21bc527b30e9b7fd2ebd5889a11eb14889bb45f71074c94c865fc1b2556" ;;
*) echo "Only amd64 and arm64 servers are supported"; exit 1 ;;
esac
echo "==> Installing packages"
export DEBIAN_FRONTEND=noninteractive NEEDRESTART_SUSPEND=1
APT="apt-get -o DPkg::Lock::Timeout=300"
$APT update -qq
$APT install -y -qq curl openssl ca-certificates >/dev/null
DEB="/tmp/3proxy-$VERSION.$ARCH.deb"
curl -fsSL -o "$DEB" "https://github.com/3proxy/3proxy/releases/download/$VERSION/3proxy-$VERSION.$ARCH.deb"
echo "$SHA $DEB" | sha256sum -c --quiet -
$APT install -y -qq "$DEB" >/dev/null
rm -f "$DEB"
echo "==> Creating login, password and ports"
LOGIN="user$(openssl rand -hex 3)"
PASS="$(openssl rand -hex 12)"
HTTP_PORT="$(shuf -i 20000-59999 -n 1)"
SOCKS_PORT="$((HTTP_PORT + 1))"
echo "$LOGIN:CL:$PASS" > "$CONF_DIR/passwd"
cat > "$CONF_DIR/3proxy.cfg" <<EOF
nscache 65536
nserver 1.1.1.1
nserver 8.8.8.8
log /logs/3proxy.log D
rotate 7
maxconn 200
users \$/conf/passwd
auth strong
deny * * 127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,169.254.0.0/16,100.64.0.0/10
deny * * * 25
allow *
proxy -a -p$HTTP_PORT
socks -p$SOCKS_PORT
EOF
chown proxy:proxy "$CONF_DIR/passwd" "$CONF_DIR/3proxy.cfg"
chmod 640 "$CONF_DIR/passwd" "$CONF_DIR/3proxy.cfg"
if command -v ufw >/dev/null && ufw status | grep -q "Status: active"; then
echo "==> Opening ports in ufw"
ufw allow "$HTTP_PORT/tcp" >/dev/null
ufw allow "$SOCKS_PORT/tcp" >/dev/null
fi
echo "==> Starting the service"
systemctl enable 3proxy >/dev/null 2>&1
systemctl restart 3proxy
sleep 2
if ! systemctl is-active --quiet 3proxy; then
echo "3proxy did not start. Details: journalctl -u 3proxy -n 30"
exit 1
fi
SERVER_IP=""
for URL in https://ifconfig.me https://api.ipify.org; do
SERVER_IP="$(curl -s --max-time 20 -x "http://$LOGIN:$PASS@127.0.0.1:$HTTP_PORT" "$URL" || true)"
[ -n "$SERVER_IP" ] && break
done
if [ -z "$SERVER_IP" ]; then
echo "The proxy runs but its test request failed. Details: tail /usr/local/3proxy/logs/3proxy.log.*"
exit 1
fi
umask 077
cat > /root/proxy.txt <<EOF
Server: $SERVER_IP
HTTP port: $HTTP_PORT
SOCKS port: $SOCKS_PORT
Login: $LOGIN
Password: $PASS
curl -x "http://$LOGIN:$PASS@$SERVER_IP:$HTTP_PORT" https://ifconfig.me
curl --socks5-hostname "$LOGIN:$PASS@$SERVER_IP:$SOCKS_PORT" https://ifconfig.me
bash check-proxy.sh $SERVER_IP $HTTP_PORT $SOCKS_PORT $LOGIN $PASS
EOF
echo
echo "Done. These details are saved in /root/proxy.txt"
echo
cat /root/proxy.txt
SCRIPT
bash install-proxy.shHere is what the script does, in order:
- installs the 3proxy package and verifies the file downloaded without tampering;
- generates a random login, password and two ports from the upper range, where scanners look less often than at 3128 and 1080;
- forbids connecting without a login and closes access from the proxy to the server's internal addresses and cloud service addresses;
- blocks mail port 25, so that if the password leaks, spammers cannot get your address on blacklists;
- removes client details from HTTP headers: the site will not see your real IP;
- enables autostart after reboot and opens the ports in ufw if that firewall is active.
At the end you will see a report like this, only with your values:
Done. These details are saved in /root/proxy.txt
Server: 203.0.113.10
HTTP port: 34512
SOCKS port: 34513
Login: user4f2a9c
Password: 8c1f0e77a2d94b36c5e1a07d
curl -x "http://user4f2a9c:8c1f0e77a2d94b36c5e1a07d@203.0.113.10:34512" https://ifconfig.me
curl --socks5-hostname "user4f2a9c:8c1f0e77a2d94b36c5e1a07d@203.0.113.10:34513" https://ifconfig.me
bash check-proxy.sh 203.0.113.10 34512 34513 user4f2a9c 8c1f0e77a2d94b36c5e1a07dCopy this data for yourself. On the server it is in the file /root/proxy.txt, and the command cat /root/proxy.txt shows it again.
Step 3. Open the ports in the host's panel
Some hosts put their own network firewall in front of the server, configured in the customer panel. If you have one, allow both ports over TCP there. If the panel has no such section, you can skip this step.
Step 4. Test the proxy from outside
Test from your own computer: this way you see the server through the eyes of the outside world. On Linux and macOS paste the block into a terminal: it creates the file check-proxy.sh. Then paste and run the last line of the installer's report, which already holds your data.
cat > check-proxy.sh <<'SCRIPT'
#!/usr/bin/env bash
# Usage: bash check-proxy.sh HOST HTTP_PORT SOCKS_PORT LOGIN PASSWORD
# Run it from your own computer: only an outside check shows the real picture.
set -u
if [ "$#" -ne 5 ]; then
echo "Usage: bash check-proxy.sh HOST HTTP_PORT SOCKS_PORT LOGIN PASSWORD"
exit 2
fi
HOST="$1"; HTTP_PORT="$2"; SOCKS_PORT="$3"; LOGIN="$4"; PASS="$5"
URL="https://ifconfig.me"
FAILED=0
pass() { echo "[ OK ] $1"; }
fail() { echo "[FAIL] $1"; FAILED=$((FAILED + 1)); }
info() { echo "[INFO] $1"; }
MY_IP=$(curl -4 -s --max-time 10 "$URL" || curl -4 -s --max-time 10 https://api.ipify.org || true)
info "Your own IP: ${MY_IP:-unknown}"
HTTP_IP=$(curl -s --max-time 20 -x "http://$LOGIN:$PASS@$HOST:$HTTP_PORT" "$URL" || true)
if [ -n "$HTTP_IP" ]; then pass "HTTP proxy works, exit IP $HTTP_IP"; else fail "HTTP proxy gave no answer"; fi
SOCKS_IP=$(curl -s --max-time 20 --socks5-hostname "$LOGIN:$PASS@$HOST:$SOCKS_PORT" "$URL" || true)
if [ -n "$SOCKS_IP" ]; then pass "SOCKS5 proxy works, exit IP $SOCKS_IP"; else fail "SOCKS5 proxy gave no answer"; fi
if [ -n "$HTTP_IP" ] && [ "$HTTP_IP" = "$MY_IP" ]; then
info "Exit IP equals your IP: fine on the server itself, a problem anywhere else"
fi
CODE=$(curl -s --max-time 20 -o /dev/null -w "%{http_code}" -x "http://$HOST:$HTTP_PORT" "http://ifconfig.me" || true)
if [ "$CODE" = "407" ]; then pass "HTTP without login is refused (407)"; else fail "HTTP without login returned $CODE, expected 407"; fi
CODE=$(curl -s --max-time 20 -o /dev/null -w "%{http_code}" -x "http://$LOGIN:wrong-$PASS@$HOST:$HTTP_PORT" "http://ifconfig.me" || true)
if [ "$CODE" = "407" ]; then pass "HTTP with a wrong password is refused (407)"; else fail "HTTP with a wrong password returned $CODE, expected 407"; fi
if [ -n "$SOCKS_IP" ]; then
if curl -s --max-time 20 -o /dev/null --socks5-hostname "$HOST:$SOCKS_PORT" "$URL"; then
fail "SOCKS5 lets you in without a login: the proxy is open"
else
pass "SOCKS5 without login is refused"
fi
fi
if [ -n "$MY_IP" ] && [ -n "$HTTP_IP" ] && [ "$HTTP_IP" != "$MY_IP" ]; then
if curl -s --max-time 20 -x "http://$LOGIN:$PASS@$HOST:$HTTP_PORT" "http://ifconfig.me/all" | grep -qF "$MY_IP"; then
fail "The site can see your own IP in the proxy headers"
else
pass "Your own IP is not visible in the headers"
fi
fi
echo
if [ "$FAILED" -eq 0 ]; then
echo "All checks passed."
else
echo "Failed checks: $FAILED"
exit 1
fi
SCRIPTIf everything is set up correctly, the output looks like this:
[INFO] Your own IP: 198.51.100.7
[ OK ] HTTP proxy works, exit IP 203.0.113.10
[ OK ] SOCKS5 proxy works, exit IP 203.0.113.10
[ OK ] HTTP without login is refused (407)
[ OK ] HTTP with a wrong password is refused (407)
[ OK ] SOCKS5 without login is refused
[ OK ] Your own IP is not visible in the headers
All checks passed.On Windows the script runs in Git Bash. Without it, two PowerShell commands are enough, and each must print your server's address. Write exactly curl.exe: plain curl in PowerShell calls a different command.
curl.exe -x "http://LOGIN:PASSWORD@HOST:HTTP_PORT" https://ifconfig.me
curl.exe --socks5-hostname "LOGIN:PASSWORD@HOST:SOCKS_PORT" https://ifconfig.meIf the check fails
| What you see | What is wrong | What to do |
|---|---|---|
| Both lines say "gave no answer", code 000 | ports closed on the way to the server | open them in the host's panel and in ufw, check the server address |
| The proxy answered only on the server itself | firewall of the host or provider | repeat step 3, contact the host's support |
| Code 407 with the correct password | typo in the login or password, or your IP is not among those allowed | compare with /root/proxy.txt and the allow line in the settings |
| SOCKS5 lets you in without a login | settings changed by hand | run the installer again, you will get new data |
| The installer says "did not start" | the service did not start | see the reason: journalctl -u 3proxy -n 30 |
| The installer says "test request failed" | the service runs, but the server does not reach the internet through the proxy | see the log: tail /usr/local/3proxy/logs/3proxy.log.* |
| Dependency error during installation | system older than Ubuntu 22.04 and Debian 12 | reinstall a fresh OS in the host's panel |
Step 5. Connect the proxy
In a browser use the HTTP port: Chrome and Firefox without extensions cannot enter a login and password for SOCKS5. Where to enter what is covered in the article on manual proxy setup. Programs usually accept a line of the form IP:PORT:LOGIN:PASSWORD, and if they need another format, the proxy converter will rewrite the line.
Connected? Open the anonymity check through the proxy: the page shows which address and headers a site sees. How HTTP differs from SOCKS5 and which port to take for specific software is covered in the protocol comparison.
How to manage the server
Run all the commands below on the server. Service status and today's connection log. 3proxy starts a new file each day and keeps them for a week. Exit the log with Ctrl+C:
systemctl status 3proxy --no-pager
tail -f "$(ls -t /usr/local/3proxy/logs/* | head -1)"Change the password. Put the login from the report in place of LOGIN. The command shows the new password, the old one stops working at once, and /root/proxy.txt keeps the previous data:
NEW="$(openssl rand -hex 12)"
sed -i "s/^LOGIN:CL:.*/LOGIN:CL:$NEW/" /usr/local/3proxy/conf/passwd
systemctl restart 3proxy
cat /usr/local/3proxy/conf/passwdAdd a second user:
echo "friend:CL:$(openssl rand -hex 12)" >> /usr/local/3proxy/conf/passwd
systemctl restart 3proxy
cat /usr/local/3proxy/conf/passwdAllow access only from your address, if it is permanent. Put your IP in place of YOUR_IP. From other addresses the proxy will answer with code 407 even with the correct password:
sed -i 's/^allow \*$/allow * YOUR_IP/' /usr/local/3proxy/conf/3proxy.cfg
systemctl restart 3proxyRemove everything when you no longer need the server:
systemctl disable --now 3proxy
apt-get purge -y 3proxy </dev/null
rm -rf /usr/local/3proxy /etc/3proxy /root/proxy.txtSecurity checklist
A proxy with an access setup error becomes public. Scanners sweep hosting addresses constantly, and an open port quickly lands in free lists: then you get other people's traffic, an eaten channel and complaints to the host. The script closes the basics, and the rest is on you:
- Enable the firewall with the command below, using the ports from the report: only SSH and the proxy stay open to the outside.
- Enable automatic system updates. 3proxy itself is a separate package, so every few months check whether a new version is out.
- Remember that the proxy login and password travel without encryption. On a public network a neighbor can intercept them, so in cafes and airports connect to the proxy through a VPN or limit access to your IP. More in the breakdown of public Wi-Fi.
- Once a month review the log for unfamiliar addresses and check the server's IP against RBL blacklists.
DEBIAN_FRONTEND=noninteractive apt-get install -y ufw unattended-upgrades </dev/null
printf 'APT::Periodic::Update-Package-Lists "1";\nAPT::Periodic::Unattended-Upgrade "1";\n' > /etc/apt/apt.conf.d/20auto-upgrades
ufw allow 22/tcp
ufw allow HTTP_PORT/tcp
ufw allow SOCKS_PORT/tcp
ufw --force enableIf your SSH runs on another port, replace 22 with it before running, or you will lose access to the server.
What you gain and what you lose
| Your own VPS | Proxy service | |
|---|---|---|
| Control and logs | entirely yours | on the operator's side |
| Addresses | one, a few at most | pools of thousands of addresses |
| Address type | host's data center | from data center to home and cellular |
| Location | your VPS's country | country choice, city on residential |
| Rotation | no, the address is permanent | per request or per session |
| Maintenance | updates and uptime are on you | included in the price |
| Entry price | VPS rental plus time | from an hourly subscription |
The line on address type matters most here. A VPS lives in a hosting subnet, and any site sees this from the autonomous system: check your server with the ASN lookup. Marketplaces and social networks treat such ranges with suspicion, and a personal server changes nothing there. Its address will not become home or cellular.
No illusions about money either. A cheap VPS shares its CPU and channel with neighbors, so evening speed drops are normal for it. Many hosts limit traffic, and overage costs noticeably more than a gigabyte from a proxy service.
When your own proxy makes sense
- A permanent IP for your services. Admin panels and internal dashboards open only from one address: a VPS gives you one cheaply and for a long time.
- A tunnel between your machines. Office and server connect directly, and you decide what goes through this point.
- Log requirements. Traffic records must stay only with you.
- Learning. Set it up, break it and fix it: that is the fastest way to understand how a proxy works from the inside.
When you need a service
A personal server drops out as soon as a task needs more than one address, rotation or a specific IP type: keeping hundreds of VPSes costs more than any plan. Scraping, price monitoring, account work and ad checks live on pools. Our plans suit them: packages with an ip:port list and residential addresses with country choice. Many people keep both: a personal server for access to their own systems and a service pool for work tasks.
Read next

Proxies in China: Who Needs a Chinese IP and What It Gives
China's segment of the web lives by its own rules, and looking at it from outside is almost useless: some sites answer only to Chinese addresses, and prices and results differ from global ones. We…
5 min read
Types of proxy servers: how HTTP differs from SOCKS5
The protocol decides how software passes a request to the proxy: an HTTP proxy reads it whole, CONNECT opens a tunnel for TLS, and SOCKS5 pipes the stream and handles UDP. We cover all four protocols…
8 min read
Proxies in Europe: Who Needs a European IP and Which to Take
Sites tie content to a visitor's country more and more: prices, search results, stock and ads differ between Berlin and Paris. We look at tasks that require a European address and match a tool to…
5 min read