Configuring a Proxy on Ubuntu and Debian, Layer by Layer
Updated:
An Ubuntu proxy setup is really four small setups, because Linux has no single proxy switch. Your shell reads environment variables, APT reads its own config directory, systemd services read unit drop-ins, and the GNOME desktop uses gsettings. Configure only the layers you use; the snippets below assume a ProxyV4 HTTP(S) proxy with a username and password.
export http_proxy=http://user:pass@ip:port https_proxy=http://user:pass@ip:portWhich file controls which program
Most "my proxy is ignored" reports on Linux come from setting the right value in the wrong place. Two rules explain nearly all of them: sudo drops your user's environment by default, and systemd services never read ~/.bashrc.
| Layer | Where it is set | Who reads it | Lasts |
|---|---|---|---|
| Login shells | ~/.bashrc or /etc/profile.d/proxy.sh | curl, wget, python, git, node | Every new login shell |
| PAM sessions | /etc/environment | All user sessions | Across reboots |
| APT | /etc/apt/apt.conf.d/80proxy | apt update, apt install | Permanently, for APT |
| systemd units | /etc/systemd/system/<svc>.service.d/proxy.conf | Docker daemon, your own services | After daemon-reload and restart |
Shell and APT configuration
Define the variables in both lower and upper case: curl and wget look at http_proxy, while other runtimes only check HTTP_PROXY. The no_proxy list keeps loopback and private ranges off the proxy.
bash
# /etc/profile.d/proxy.sh - shells and CLI tools
sudo tee /etc/profile.d/proxy.sh > /dev/null << 'EOF'
export http_proxy="http://USER:PASS@IP:PORT"
export https_proxy="http://USER:PASS@IP:PORT"
export HTTP_PROXY="http://USER:PASS@IP:PORT"
export HTTPS_PROXY="http://USER:PASS@IP:PORT"
export no_proxy="localhost,127.0.0.1,::1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16"
export NO_PROXY="$no_proxy"
EOF
source /etc/profile.d/proxy.sh
# /etc/apt/apt.conf.d/80proxy - package manager
sudo tee /etc/apt/apt.conf.d/80proxy > /dev/null << 'EOF'
Acquire::http::Proxy "http://USER:PASS@IP:PORT/";
Acquire::https::Proxy "http://USER:PASS@IP:PORT/";
EOF
If the password contains characters such as @, : or #, percent-encode them in these URLs.
Services managed by systemd
A daemon started by systemd only sees variables declared in its unit. Put them in a drop-in, reload, and restart the service. The Docker guide covers the Docker daemon and containers in detail.
bash
# /etc/systemd/system/<svc>.service.d/proxy.conf
[Service]
Environment="HTTP_PROXY=http://USER:PASS@IP:PORT"
Environment="HTTPS_PROXY=http://USER:PASS@IP:PORT"
Environment="NO_PROXY=localhost,127.0.0.1"
sudo systemctl daemon-reload
sudo systemctl restart <svc>
sudo, shared servers and the desktop
- sudo: run
sudo -E curl ...to keep your exported variables, or make it permanent withDefaults env_keep += "http_proxy https_proxy HTTP_PROXY HTTPS_PROXY no_proxy NO_PROXY"added throughsudo visudo. - Credentials on multi-user machines: these files hold the proxy password in plain text. Lock them down, for example
sudo chmod 600 /etc/apt/apt.conf.d/80proxy. - GNOME desktop: Settings → Network → Network Proxy → Manual, or
gsettings set org.gnome.system.proxy mode 'manual'plus the host and port keys underorg.gnome.system.proxy.http.
Testing and troubleshooting
After sourcing the profile, curl -s https://api.ipify.org should print the proxy IP rather than the server's own address. For a full report on country and owner, paste the IP into IP lookup. The curl and Python requests guides show per-command alternatives when you would rather not proxy the whole shell.
- `407 Proxy Authentication Required`: wrong credentials or an unencoded special character in the password; see the 407 page.
- apt works only with sudo -E: the 80proxy file is missing or has a syntax error (each line ends in a semicolon).
- Connections hang: outbound access to the proxy port may be blocked by the server's firewall; check firewall causes.
Step by step
- 1
Write /etc/profile.d/proxy.sh
Export http_proxy, https_proxy and no_proxy in lower case and HTTP_PROXY, HTTPS_PROXY and NO_PROXY in upper case so every CLI tool finds them.
- 2
Give APT its own proxy file
Because sudo apt update ignores your shell variables, create /etc/apt/apt.conf.d/80proxy with Acquire::http::Proxy and Acquire::https::Proxy.
- 3
Add systemd drop-ins where needed
For each daemon that must use the proxy, create a proxy.conf drop-in with Environment lines, then run daemon-reload and restart it.
- 4
Confirm the exit IP
Run
source /etc/profile.d/proxy.shand thencurl -s https://api.ipify.org; the output should be your proxy's IP.
Frequently asked questions
Do I really need both http_proxy and HTTP_PROXY?
Yes. Some tools such as curl and wget check the lowercase name, others only the uppercase one. Setting both avoids inconsistent behaviour.
Why does sudo apt update not use my proxy?
sudo resets the environment unless you pass -E. A file in /etc/apt/apt.conf.d/ makes APT use the proxy regardless.
How do I set the proxy in the Ubuntu desktop GUI?
Open Settings → Network → Network Proxy and choose Manual, or set it with gsettings under org.gnome.system.proxy.
Is a static proxy useful on a Linux server?
Yes, when a remote API or partner allowlists your IP. A private IPv4 keeps the same address for as long as you renew it, so the allowlist entry stays valid.
Fixed-IP proxies for servers and scripts
HTTP(S) with username and password, unlimited bandwidth on private IPv4, and the same address on every renewal.
Compare prices