---
title: "Squid Proxy on Ubuntu 24.04: Install, Auth and squid.conf"
description: "Squid is an open-source forward proxy that relays requests from its own IP. Install it on Ubuntu 24.04, lock it with ACLs and basic auth, then tune caching."
url: https://proxynet.io/blog/squid-proxy-setup
date: 2026-09-24
author: "Acar Diveroli"
category: "Tutorial, Proxies"
lang: en
---

# Squid Proxy on Ubuntu 24.04: Install, Auth and squid.conf

A five-person data team wants its test servers to download packages from one place and to reach a supplier's API from the same IP address every time. Someone installs Squid on a small VPS in ten minutes. A week later, `access.log` is full of addresses nobody recognises: the configuration came from a forum post ending in `http_access allow all`, and strangers now send their traffic out through the team's IP.

This guide installs Squid on Ubuntu 24.04 without that mistake. It covers what Squid is, the order in which it checks a request and what one server can and cannot give you. Then comes one complete configuration file with an IP allowlist, a login, a disk cache and header settings, a parent proxy with `cache_peer`, and the commands that test it.

> **Note: Short answer**
>
> Squid is an open-source forward proxy: it sends your clients' requests to the target site from its own IP address and can cache plain HTTP responses. On Ubuntu 24.04 you install it with `sudo apt install squid`; it listens on port 3128 and reads `/etc/squid/squid.conf`. Out of the box it accepts requests only from the server itself. To use it from other machines, add an IP allowlist and a username and password, and keep `http_access deny all` as the last rule. One server is one data center IP in one location, so jobs that need other countries or many addresses need a commercial proxy.

## What is a Squid proxy?

Squid is an open-source caching proxy server. A proxy server sends requests on your behalf and passes the answers back ([What Is a Proxy Server?](/blog/what-is-a-proxy-server)). Squid usually runs as a forward proxy that works for the clients behind it, not as a reverse proxy in front of a website ([Forward Proxy vs Reverse Proxy](/blog/forward-vs-reverse-proxy)). It carries HTTP, HTTPS through `CONNECT` tunnels and FTP, with access rules, login helpers, a cache and a request log.

The Squid project's current stable release is 7.7, published on 24 August 2026, and its developers support only the latest stable release. Ubuntu 24.04 ships Squid 6.14, package `6.14-0ubuntu0.24.04.4` in [noble-updates](https://packages.ubuntu.com/noble-updates/squid), and its security fixes arrive through normal Ubuntu updates. This guide uses that package.

## How does Squid handle a request?

The order of these steps explains most configuration mistakes.

1. **The client connects** to the port in `http_port`, 3128 in Ubuntu's configuration.
2. **Squid reads the `http_access` lines from top to bottom.** The first line whose conditions all match decides. The [http_access documentation](https://www.squid-cache.org/Doc/config/http_access/) adds that when no line matches, Squid does the opposite of the last line, so every list should end with `http_access deny all`.
3. **A rule that needs a login asks for one.** When Squid reaches a `proxy_auth` condition without valid credentials, it answers `407 Proxy Authentication Required` ([Proxy Authentication Methods](/blog/proxy-authentication-methods)).
4. **Plain HTTP is looked up in the cache.** A fresh stored copy is a hit and never leaves the server; anything else is a miss and is fetched from the site.
5. **HTTPS becomes a tunnel.** After `CONNECT example.com:443` succeeds, Squid only relays encrypted bytes. [RFC 9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-connect) calls this "blind forwarding of data", so Squid can neither cache the page nor add headers inside the tunnel.
6. **A parent proxy takes over if you set one** with `cache_peer` and `never_direct`.
7. **Squid writes one line to `access.log`** with the client, result code, size, URL and username.

## What does your own Squid server give you, and what doesn't it?

| Question | Your own Squid (one VPS) | Commercial datacenter proxy | Residential or rotating pool |
|---|---|---|---|
| Exit IP | The VPS's single data center IP | The provider's data center IPs, several if needed | Home connection IPs, per request or session |
| Location | The city where the server runs | A choice of the provider's countries | A country, sometimes a city |
| Maintenance | You: updates, rules, passwords, logs | The provider; you manage credentials | The provider; you manage credentials |
| Cache and access control | HTTP cache, rules, one central log | No cache; users in a dashboard | No cache; users in a dashboard |

Squid gives you control over who connects, what gets cached and what gets logged. It cannot give you a second address: a site that sees hundreds of requests a minute from that one data center IP will slow it down or block it ([Residential vs Datacenter Proxy](/blog/residential-vs-datacenter-proxy)).

## How do you install Squid on Ubuntu 24.04?

`apache2-utils` adds `htpasswd` for the password file. Keeping a read-only copy of the original configuration follows the official [Ubuntu Server guide](https://ubuntu.com/server/docs/how-to/web-services/install-a-squid-server/).

```bash
sudo apt update
sudo apt install squid apache2-utils
squid -v | head -n 1                       # the installed version
systemctl status squid --no-pager          # should say "active (running)"

sudo cp /etc/squid/squid.conf /etc/squid/squid.conf.original
sudo chmod a-w /etc/squid/squid.conf.original

# where will your own rules be read?
grep -n "include /etc/squid/conf.d" /etc/squid/squid.conf
grep -n "^http_access deny all" /etc/squid/squid.conf
```

Put your settings in a file under `/etc/squid/conf.d/`, so package upgrades leave them alone. The Debian packaging that Ubuntu builds on places `include /etc/squid/conf.d/*.conf` under the comment `INSERT YOUR OWN RULE(S) HERE`: after the rules that block unsafe ports, before `http_access allow localhost` and `http_access deny all`. The `include` line number from `grep` must be smaller than the `deny all` one; if not, put your lines into `squid.conf` at that comment. The folder's `debian.conf` sets `logfile_rotate 0`, because logrotate handles the logs.

## A complete team.conf for a locked-down proxy

Save this as `/etc/squid/conf.d/team.conf`. Replace the documentation network `203.0.113.0/24` with your office network or your team's fixed IPs.

```text
# /etc/squid/conf.d/team.conf
# Read inside the http_access list of squid.conf, above "http_access deny all".
# Never add "http_access allow all": it turns this server into an open proxy.

# 1. Which networks may connect
acl team_net src 203.0.113.0/24

# 2. Username and password from /etc/squid/passwords.
#    Keep the auth_param lines above the proxy_auth ACL.
auth_param basic program /usr/lib/squid/basic_ncsa_auth /etc/squid/passwords
auth_param basic children 5 startup=5 idle=1
auth_param basic realm Team proxy
auth_param basic credentialsttl 2 hours
acl team_users proxy_auth REQUIRED

# 3. Allow only when BOTH match: the right network AND a valid login.
#    Everything else falls through to "http_access deny all".
http_access allow team_net team_users

# 4. Do not pass client addresses in plain HTTP requests
forwarded_for delete
via off

# 5. Cache: memory, largest object to store, then the disk cache
cache_mem 512 MB
maximum_object_size 512 MB
cache_dir ufs /var/spool/squid 10000 16 256
```

Then add users, check the syntax, restart once and open the port only to known addresses:

```bash
sudo htpasswd -c /etc/squid/passwords team1   # -c creates the file: first user only
sudo htpasswd /etc/squid/passwords team2      # later users: without -c
sudo chown root:proxy /etc/squid/passwords
sudo chmod 640 /etc/squid/passwords

sudo squid -k parse                           # prints errors and warnings, if any
sudo systemctl restart squid                  # once, for the new cache_dir
sudo tail -n 20 /var/log/squid/cache.log      # startup messages

sudo ufw allow OpenSSH                        # keep your SSH session reachable
sudo ufw allow from 203.0.113.0/24 to any port 3128 proto tcp
sudo ufw enable
```

> **Warning: Do not build an open proxy**
>
> Scanners search the internet for proxies that accept any address, and the spam, attacks and scraping sent through yours are traced to your IP. Keep the network ACL, the login and the final `deny all` together, and open 3128 only to known addresses ([Are Free Proxies Safe?](/blog/are-free-proxies-safe)).

## How do you write the acl and http_access rules?

An `acl` line names a condition; an `http_access` line combines names into a decision. Conditions on one line must all match, so `allow team_net team_users` means "from our network and logged in". Separate lines are alternatives: for a second office, add `acl office2 src 198.51.100.0/24` and `http_access allow office2 team_users`.

Position matters as much as content. An `allow` below `http_access deny all` is never reached, and every client gets `403`. Leave the rules above the include untouched: `deny CONNECT !SSL_ports` lets tunnels reach only port 443. RFC 9110 advises limiting `CONNECT` to known ports, because a proxy that tunnels to any port can be used to relay spam to port 25.

To change the port, edit the existing `http_port 3128` line in `squid.conf` instead of adding a second one, and update the firewall. A new port protects nothing; the ACL and the firewall do. What 3128 and 8080 mean is in [Port 8080 and Other Proxy Ports](/blog/port-8080).

## How do you add a username and password?

`htpasswd` stores one line per user with a hashed password. Its default hash is MD5, which Squid's `basic_ncsa_auth` helper reads; on Ubuntu the helper is `/usr/lib/squid/basic_ncsa_auth`. It runs as the `proxy` user, hence the file's `proxy` group. The `auth_param` lines start up to five helpers, set the login prompt text and let Squid trust a correct login for two hours before checking the file again.

Squid's `auth_param` documentation states that a client is asked for credentials only when an `http_access` rule evaluates a `proxy_auth` ACL. Configure `auth_param` without using `team_users` in `http_access`, and Squid never asks for a password.

Basic authentication sends the password Base64-encoded, not encrypted, in every `Proxy-Authorization` header between client and Squid. Anyone watching that path can read it, which is why the allowlist stays next to the password. Reading a `407` is covered in [Proxy Authentication Methods](/blog/proxy-authentication-methods).

## How do you set up caching and read the logs?

`cache_mem` sets the memory for hot objects (default 256 MB). `cache_dir ufs /var/spool/squid 10000 16 256` adds up to 10,000 MB of disk cache in 16 first-level and 256 second-level folders; Squid's documentation warns against entering the whole disk size. `maximum_object_size` defaults to 4 MB, which leaves larger package files uncached, so raise it. It sets the default size limit for every `cache_dir`, which is why the file above puts it first.

`squid -z` creates the cache folders, and Ubuntu's service file runs `squid --foreground -z` before every start, so the restart builds them. For later rule or user changes, `sudo systemctl reload squid` sends the same signal as `squid -k reconfigure`.

The cache only helps plain HTTP. Ubuntu's mirrors usually use `http://` addresses and apt checks package signatures, so CI machines that point apt at Squid download each package once ([Linux Proxy Settings](/blog/linux-proxy-settings)). HTTPS never produces a hit. Opening it for caching (SSL bump) needs Squid's certificate on every client and the separate `squid-openssl` package, and is outside this guide.

`/var/log/squid/access.log` has one line per request, and `cache.log` holds startup messages and errors; logrotate rotates both daily and keeps two old copies. The result code tells you what happened:

| Result code | Meaning |
|---|---|
| `TCP_MISS/200` | Fetched from the site |
| `TCP_HIT/200`, `TCP_MEM_HIT/200` | Served from the disk or memory cache |
| `TCP_TUNNEL/200` | HTTPS tunnel; Squid saw only host and port |
| `TCP_DENIED/407` | No login or a wrong one |
| `TCP_DENIED/403` | Refused by `http_access`: wrong network or rule order |

## How do you remove the Via and X-Forwarded-For headers?

By default Squid appends the client's IP to `X-Forwarded-For` (`forwarded_for on`) and adds a `Via` header (`via on`). `forwarded_for delete` removes the header, `off` writes `unknown` instead of the address, and `via off` drops `Via`. Both work only on plain HTTP; inside a tunnel Squid adds nothing anyway. To check the result with an echo request, see [Anonymous Proxy Levels](/blog/anonymous-proxy-levels).

## One exit for the team: cache_peer with a parent proxy

A team on a commercial proxy may not want its password on every laptop and CI job. Squid can sit in between: people log in to Squid with their own accounts, and only the server knows the commercial credentials. Add to `team.conf`:

```text
# Send every request through the parent proxy. Clients never see its password.
cache_peer pr.proxynet.io parent 8000 0 no-query default login=user:pass
never_direct allow all
```

Following the [cache_peer documentation](https://www.squid-cache.org/Doc/config/cache_peer/): host, type `parent`, proxy port `8000`, and ICP port `0` because the peer answers no ICP queries. `no-query` turns those queries off, `default` makes it the last-resort parent, and `login=` sends the parent's credentials; write a `%` in the password as `%%`.

Without `never_direct allow all`, Squid may fetch some requests directly from the VPS's own IP. For HTTPS, Squid passes the `CONNECT` to the parent. In `access.log`, the hierarchy field then names the parent with a code such as `DEFAULT_PARENT` instead of `HIER_DIRECT`.

A password change is now one line and a reload, every request is logged with the member's username, and plain HTTP is still cached. With a [Rotating Proxy](https://proxynet.io/rotating-proxy) as parent, the provider changes the exit IP while Squid keeps one address ([IP Rotation Explained](/blog/ip-rotation-explained)). The chain manages credentials; it does not hide who you are, and the provider's terms and each site's rules still apply.

## How do you connect a client and test it?

Run this from a machine in the allowed network; `198.51.100.20` stands for your server.

```bash
# 1. Without a login: Squid asks for one
curl -x http://198.51.100.20:3128 https://httpbin.org/ip
# curl: (7) CONNECT tunnel failed, response 407

# 2. With a login: the answer shows the server's IP, not yours
curl -x http://team1:pass@198.51.100.20:3128 --retry 3 https://httpbin.org/ip

# 3. On the server: the last three requests
sudo tail -n 3 /var/log/squid/access.log
```

We ran the curl side with curl 8.21 against a local test proxy that requires a login: the first command printed the line above, the second returned the proxy's exit address. `--retry 3` repeats after a timeout or a transient HTTP code such as `429` or `503`, never after a `407`. More in [cURL with a Proxy](/blog/curl-proxy) and [How to Test a Proxy](/blog/how-to-test-a-proxy).

## What do you use your own proxy server for?

- **A fixed exit IP for an API:** only the API traffic goes through Squid ([Static IP for API Access](/blog/static-ip-for-api-access)).
- **Office web access control:** `dstdomain` ACLs and `access.log`, with employees told beforehand ([Proxy vs Firewall](/blog/proxy-vs-firewall)).
- **Office browser settings:** a PAC file tells each browser when to use Squid ([PAC File](/blog/pac-file)).
- **A package cache for CI machines:** apt fetches each plain HTTP package once ([Linux Proxy Settings](/blog/linux-proxy-settings)).
- **Not for data work across countries:** price checks and scraping by location need many addresses ([data scraping](/data-scraping)).

## Common mistakes

- **`http_access allow all`.** An open proxy, whose IP soon lands on block lists ([IP Blacklist](/blog/ip-blacklist)).
- **`auth_param` without `proxy_auth` in `http_access`.** No password is ever asked.
- **An `allow` below `deny all`.** Never reached; everyone gets `403`.
- **3128 open to the internet.** A password alone invites guessing, and basic auth sends it unencrypted.
- **Expecting HTTPS cache hits.** Tunnels are never cached.
- **Skipping `squid -k parse`.** A typo stops the service; `journalctl -u squid` shows why.
- **`maximum_object_size` left at 4 MB** for a package cache, or a `cache_dir` bigger than the free disk.
- **Heavy scraping from the VPS IP.** Sites answer `429`, then block ([HTTP Status Codes in Web Scraping](/blog/http-status-codes-web-scraping)).

## Decision guide

| Need | Recommendation |
|---|---|
| The team must reach an API from one IP | Squid on a fixed-IP VPS with allowlist and login, or a [Static Proxy](https://proxynet.io/static-proxy) |
| CI machines download the same packages again and again | Squid with `cache_dir` and a larger `maximum_object_size`; gains come from HTTP mirrors |
| The office wants to see and limit visited sites | `dstdomain` ACLs and `access.log`; inform employees first |
| The commercial proxy password should stay on one server | Squid for clients, `cache_peer` to the provider, `never_direct allow all` |
| You need IPs in other countries, or many IPs | Not your own Squid: a datacenter proxy, or a residential and rotating pool |
| You want HTTPS pages cached | Not with the default package; cache plain HTTP sources only |

## Frequently asked questions

### Which port does Squid use?

Ubuntu's configuration sets `http_port 3128`, so Squid listens on 3128 after installation. You can change that line and the firewall rule together, but a different port adds no protection; the network ACL, the login and the firewall do. What the common proxy port numbers mean is explained in our [port 8080 guide](/blog/port-8080).

### Can Squid cache HTTPS sites?

Not in its default setup. An HTTPS request arrives as a `CONNECT` tunnel, and Squid relays encrypted bytes without seeing the page, so there is nothing to store. SSL bump, which opens the traffic, needs a Squid certificate on every client device and the `squid-openssl` package, and is outside this guide.

### How do I apply squid.conf changes without stopping the service?

Run `sudo squid -k parse` first, so a typo cannot take the proxy down. Then run `sudo systemctl reload squid`, which sends the same signal as `squid -k reconfigure` and keeps the service running. After adding or moving a `cache_dir`, restart once instead, so the service creates the cache folders.

### Where are the Squid logs, and how do I read them?

On Ubuntu they are in `/var/log/squid/`: `access.log` has one line per request, `cache.log` has startup messages and errors. In `access.log`, read the result code: `TCP_HIT` came from the cache, `TCP_MISS` from the site, `TCP_TUNNEL` is HTTPS, and `TCP_DENIED` with `407` or `403` means refused.

### What is the difference between Squid and Tinyproxy?

Tinyproxy describes itself as a light-weight HTTP and HTTPS proxy daemon for systems too small for a full proxy, and its configuration manual lists no cache settings. Squid adds a memory and disk cache, detailed ACLs, several login helpers and parent proxy chains. For plain forwarding on a small device, Tinyproxy may be enough.

### Does my own Squid server hide my identity?

Only partly. Sites see the VPS's IP instead of your home address, and `forwarded_for delete` with `via off` removes the proxy headers from plain HTTP. But that IP belongs to a data center, is rented in your name and always comes from one place. Squid is a tool for access control and a shared exit, not for anonymity.

## Summary

Squid gives you your own forward proxy with access control, a cache for plain HTTP and one log for every request. A safe setup keeps three things in order: a network ACL, a `proxy_auth` login used in `http_access`, and `http_access deny all` at the end, with the firewall open only to known addresses. The limit is the address: one server is one data center IP in one place. When a job needs more addresses or other countries, a [Datacenter Proxy](https://proxynet.io/datacenter-proxy) or a [Residential Proxy](https://proxynet.io/residential-proxy) fills the gap, and our [proxy services](/proxy) page compares the options.
