Varnish 101: Protecting Paths with HTTP Basic Authentication on Upsun

Varnish 101: Protecting Paths with HTTP Basic Authentication on Upsun

October 17, 2025· Jared Wright
Jared Wright
·Reading time: 5 minutes

Welcome to the first article in our Varnish series, where we’ll explore practical techniques for leveraging Varnish Cache (soon to be rebranded as Vinyl) beyond simple caching. While many developers view Varnish as just an HTTP accelerator, its VCL (Varnish Configuration Language) provides powerful capabilities for traffic control, security, and request processing—all before requests reach your backend application.

Throughout this series, we’ll cover practical implementations including path protection, rate limiting, URL normalization, and advanced traffic filtering. This first article focuses on implementing HTTP Basic Authentication directly in VCL to protect specific paths like admin areas and staging environments.

Why Protect Paths in Varnish?

Varnish Cache sits between your application and your users as a powerful HTTP accelerator. Beyond caching, it’s the perfect place to implement simple access controls for specific paths—blocking unauthorized requests before they consume backend resources.

While Upsun offers environment-level HTTP access control, implementing authentication directly in VCL gives you more flexibility:

  • Path-specific protection: Secure only certain URLs (e.g., /admin, /staging)
  • Multiple credential sets: Use different passwords for different areas
  • Custom logic: Combine authentication with other VCL conditions
  • Edge enforcement: Block unauthorized traffic at the Varnish layer

Understanding HTTP Basic Authentication

HTTP Basic Authentication is a simple challenge-response mechanism where:

  1. Client requests a protected resource
  2. Server responds with 401 Unauthorized and a WWW-Authenticate header
  3. Browser displays a login prompt
  4. Client resends the request with an Authorization header containing Base64-encoded credentials
  5. Server validates credentials and either allows or denies access

In VCL, we implement this by checking the Authorization header against known credentials and generating synthetic responses for authentication challenges.

Implementation

HTTP Basic Auth in VCL requires two parts: checking credentials in vcl_recv and generating the authentication challenge in vcl_synth.

Part 1: Credential Verification in vcl_recv

.upsun/config.vcl
sub vcl_recv {
...
    # --- Basic Auth ---
    # Check if the path is restricted.
    if (req.url ~ "^/admin") {
        # Check for the Authorization header
        if (!req.http.Authorization) {
            # If no Authorization header, request credentials
            return (synth(401, "Authentication Required"));
        }

        # Decode the Base64 encoded credentials (e.g., "Basic dXNlcm5hbWU6cGFzc3dvcmQ=")
        # In this example, we'll hardcode the expected credentials
        # "username:password" and "admin:admin" Base64 encoded
        # Use https://www.debugbear.com/basic-auth-header-generator to generate credentials
        if (req.http.Authorization !~ "^Basic (YWRtaW46YWRtaW4=|dXNlcm5hbWU6cGFzc3dvcmQ=)$") {
            return (synth(401, "Authentication Required"));
        }
    }
...
}

Part 2: Authentication Challenge in vcl_synth

.upsun/config.vcl
sub vcl_synth {
...
    if (resp.status == 401) {
        set resp.http.WWW-Authenticate = {"Basic realm="Restricted area""};
        set resp.http.Content-Type = "text/plain";
        set resp.body = "Access Denied";
        return (deliver);
    }
...
}

How It Works

  1. Path Matching: The condition if (req.url ~ "^/admin") identifies protected paths. The ^ anchor ensures only paths starting with /admin are restricted (e.g., /admin, /admin/dashboard, but not /public/admin).

  2. Authorization Header Check: if (!req.http.Authorization) verifies whether the client sent credentials. If not, we immediately return a 401 status, triggering the authentication challenge.

  3. Credential Validation: The second check validates the Base64-encoded credentials:

    • HTTP Basic Auth sends credentials as Authorization: Basic <base64-string>
    • The base64 string encodes username:password
    • Example: admin:admin becomes YWRtaW46YWRtaW4=
    • Example: username:password becomes dXNlcm5hbWU6cGFzc3dvcmQ=
  4. Multiple Allowed Credentials: The regex pattern (YWRtaW46YWRtaW4=|dXNlcm5hbWU6cGFzc3dvcmQ=) allows multiple username/password combinations using alternation (OR logic).

  5. Synthetic Response: When authentication fails, return (synth(401, "Authentication Required")) triggers vcl_synth with a 401 status.

  6. WWW-Authenticate Header: In vcl_synth, the WWW-Authenticate header tells the browser to display the login prompt. The realm parameter appears in the browser’s authentication dialog.

Generating Base64 Credentials

To create your own credential strings, use the DebugBear Basic Auth Header Generator or encode manually:

Terminal
# Using command line
echo -n "myuser:mypassword" | base64
# Output: bXl1c2VyOm15cGFzc3dvcmQ=

# Using Python
python3 -c "import base64; print(base64.b64encode(b'myuser:mypassword').decode())"
# Output: bXl1c2VyOm15cGFzc3dvcmQ=

Then add the encoded string to your VCL pattern:

.upsun/config.vcl
sub vcl_recv {
...
    if (req.http.Authorization !~ "^Basic (YWRtaW46YWRtaW4=|dXNlcm5hbWU6cGFzc3dvcmQ=|bXl1c2VyOm15cGFzc3dvcmQ=)$") {
        return (synth(401, "Authentication Required"));
    }
...
}

Protecting Multiple Paths

You can protect different areas with different credentials:

.upsun/config.vcl
sub vcl_recv {
...
    # Admin area with one set of credentials
    if (req.url ~ "^/admin") {
        if (!req.http.Authorization ||
            req.http.Authorization !~ "^Basic YWRtaW46YWRtaW4=$") {
            return (synth(401, "Admin Authentication Required"));
        }
    }

    # Staging area with different credentials
    if (req.url ~ "^/staging") {
        if (!req.http.Authorization ||
            req.http.Authorization !~ "^Basic c3RhZ2luZzpzdGFnZTEyMw==$") {
            return (synth(401, "Staging Authentication Required"));
        }
    }

    # API with third set of credentials
    if (req.url ~ "^/api/internal") {
        if (!req.http.Authorization ||
            req.http.Authorization !~ "^Basic YXBpOnNlY3JldGtleQ==$") {
            return (synth(401, "API Authentication Required"));
        }
    }
...
}

Security Considerations

Important: HTTP Basic Auth has several security limitations:

  1. Credentials in VCL: The credentials are stored in plain text (Base64 is just encoding, not encryption) in your VCL configuration. Anyone with access to your VCL can decode them instantly.

  2. HTTPS Required: Always use HTTPS when deploying Basic Auth. Over HTTP, credentials are transmitted in the clear and can be intercepted.

  3. Not for Primary Production User Auth: This approach is suitable for:

    • Restricting admin areas with a shared password
    • Adding a simple barrier to work-in-progress content
    • Protecting staging environments from public access
    • Securing internal APIs with simple tokens

    Do NOT use for:

    • Production user authentication (use proper session-based auth in your application)
    • Primary protection for sensitive customer data
    • Any scenario requiring user-specific permissions or audit trails

Use Cases

HTTP Basic Auth in Varnish is ideal for:

Admin Areas

Protect administrative interfaces that should only be accessible to team members:

.upsun/config.vcl
if (req.url ~ "^/admin") {
    # Check credentials
}

Staging Content

Hide work-in-progress content from public view while allowing authorized reviewers access:

.upsun/config.vcl
if (req.url ~ "^/preview/") {
    # Check credentials
}

Internal APIs

Add a simple authentication layer for internal API endpoints:

.upsun/config.vcl
if (req.url ~ "^/api/internal/") {
    # Check API credentials
}

Conclusion

HTTP Basic Authentication in Varnish VCL provides a lightweight way to protect specific paths without adding complexity to your application code. While it’s not suitable for production user authentication, it’s perfect for admin areas, staging content, and internal tools.

Ready to take your Varnish security further? In our next article, Varnish 102: Rate Limiting, we’ll explore protecting your backend from abuse using the vsthrottle VMOD to implement intelligent request throttling.

Last updated on