Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 139 additions & 0 deletions content/doc/administrate/cache.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,145 @@
The `vcl 4.1;` and backend section of the `varnish.vcl` configuration file are not necessary as they are already handled by Clever Cloud.
If you have a PHP FTP application or if your `varnish.vcl` file is on an FS Bucket, make sure you redeploy the application for the changes to take effect.

## Varnish to restrict access to your application

### Block IP addresses

```bash {filename="clevercloud/varnish.vcl"}
sub vcl_recv {
# Local health check
if (client.ip == "127.0.0.1" && !req.http.X-Forwarded-For) {
return (synth(200, "OK"));
}

# We don't rely on client.ip which send the load balancer IP address
# We check if the IP to block is included in the Forwarded header instead
if (req.http.Forwarded ~ "X.X.X.X") {
return (synth(403, "Blocked"));
}

# Use return (hash); to use the cache
return (pass);
}

sub vcl_synth {
if (resp.status == 403) {
set resp.http.Content-Type = "text/plain";
synthetic("Access denied");
return (deliver);
}
}
```

Replace `X.X.X.X` with the IP address you want to block.

If you want to block multiple IP addresses, you can use a regular expression like this:

```bash
if (req.http.Forwarded ~ "^(X.X.X.X|Y.Y.Y.Y|Z.Z.Z.Z)$") {
return (synth(403, "Blocked"));
}
```

To be able to configure with an environment variable multiple IPs to block, CIDR, exceptions, etc. use the following example:

Check failure on line 73 in content/doc/administrate/cache.md

View workflow job for this annotation

GitHub Actions / vale

[vale] content/doc/administrate/cache.md#L73

[Vale.Spelling] Did you really mean 'IPs'?
Raw output
{"message": "[Vale.Spelling] Did you really mean 'IPs'?", "location": {"path": "content/doc/administrate/cache.md", "range": {"start": {"line": 73, "column": 63}}}, "severity": "ERROR"}

Check notice on line 73 in content/doc/administrate/cache.md

View workflow job for this annotation

GitHub Actions / vale

[vale] content/doc/administrate/cache.md#L73

[Google.Acronyms] Spell out 'CIDR', if it's unfamiliar to the audience.
Raw output
{"message": "[Google.Acronyms] Spell out 'CIDR', if it's unfamiliar to the audience.", "location": {"path": "content/doc/administrate/cache.md", "range": {"start": {"line": 73, "column": 77}}}, "severity": "INFO"}

- [Varnish IP blocking with environment variable](https://github.com/CleverCloud/varnish-examples/blob/main/varnish-ip-blocking/varnish.vcl)

### Ask for a login/password (Basic authentication)

```bash {filename="clevercloud/varnish.vcl"}
sub vcl_recv {
# Local health check
if (client.ip == "127.0.0.1" && !req.http.X-Forwarded-For) {
return (synth(200, "OK"));
}

if (!req.http.Authorization) {
return (synth(401, "Authentication Required"));
}

if (req.http.Authorization !~ "^Basic ") {
return (synth(401, "Basic Authentication Required"));
}

set req.http.X-Auth-Credentials = regsub(req.http.Authorization, "^Basic ", "");

if (req.http.X-Auth-Credentials != "CREDENTIALS") {
return (synth(401, "Valid Basic Authentication Required"));
}
}

sub vcl_synth {
if (resp.status == 200) {
set resp.http.Content-Type = "text/plain";
synthetic("OK");
return (deliver);
}

if (resp.status == 401) {
set resp.http.Content-Type = "text/html; charset=utf-8";
set resp.http.WWW-Authenticate = "Basic realm='Restricted Area'";
synthetic("<html><body><h1>Authentication Required</h1></body></html>");

return (deliver);
}

# Use return (hash); to use the cache
return (pass);
}
```

The `CREDENTIALS` string should be replaced with the base64 encoded value of `username:password`. You can use the following command to generate it on UNIX-based systems:

Check notice on line 121 in content/doc/administrate/cache.md

View workflow job for this annotation

GitHub Actions / vale

[vale] content/doc/administrate/cache.md#L121

[Google.Passive] In general, use active voice instead of passive voice ('be replaced').
Raw output
{"message": "[Google.Passive] In general, use active voice instead of passive voice ('be replaced').", "location": {"path": "content/doc/administrate/cache.md", "range": {"start": {"line": 121, "column": 33}}}, "severity": "INFO"}

Check notice on line 121 in content/doc/administrate/cache.md

View workflow job for this annotation

GitHub Actions / vale

[vale] content/doc/administrate/cache.md#L121

[Google.Acronyms] Spell out 'UNIX', if it's unfamiliar to the audience.
Raw output
{"message": "[Google.Acronyms] Spell out 'UNIX', if it's unfamiliar to the audience.", "location": {"path": "content/doc/administrate/cache.md", "range": {"start": {"line": 121, "column": 151}}}, "severity": "INFO"}

```bash
echo -n "username:password" | base64
```

### Bearer token authentication

```bash {filename="clevercloud/varnish.vcl"}
import env;

sub vcl_recv {
# Local health check
if (client.ip == "127.0.0.1" && !req.http.X-Forwarded-For) {
return (synth(200, "OK"));
}

if (!req.http.Authorization) {
return (synth(401, "Authentication Required"));
}

if (req.http.Authorization !~ "^Bearer ") {
return (synth(401, "Bearer token Required"));
}

set req.http.X-Token = regsub(req.http.Authorization, "^Bearer ", "");

if (req.http.X-Token != env.get("CC_VARNISH_BEARER_TOKEN")) {
return (synth(401, "Valid Bearer token Required"));
}

# Use return (hash); to use the cache
return (pass);
}

sub vcl_synth {
if (resp.status == 200) {
set resp.http.Content-Type = "text/plain";
synthetic("OK");
return (deliver);
}

if (resp.status == 401) {
set resp.http.Content-Type = "text/html; charset=utf-8";
synthetic("<html><body><h1>Authentication Required</h1></body></html>");

return (deliver);
}
}
```

## Listen on the right port

Once varnish is enabled, your application should no longer listen on port **8080**, but on port **8081**. Because it's Varnish that will listen on port **8080**, and it will have in its configuration your application as backend.
Expand Down
Loading