summaryrefslogtreecommitdiff
path: root/installation/pleroma.vcl
blob: ad5bb3c6cb83ef7132dcb30b8b1fab75d5a4bafc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
vcl 4.0;
import std;

backend default {
    .host = "127.0.0.1";
    .port = "4000";
}

# ACL for IPs that are allowed to PURGE data from the cache
acl purge {
    "127.0.0.1";
}

sub vcl_recv {
    # Redirect HTTP to HTTPS
    if (std.port(server.ip) != 443) {
        set req.http.x-redir = "https://" + req.http.host + req.url;
        return (synth(750, ""));
    }

    # Pipe if WebSockets request is coming through
    if (req.http.upgrade ~ "(?i)websocket") {
        return (pipe);
    }

    # Allow purging of the cache
    if (req.method == "PURGE") {
        if (!client.ip ~ purge) {
          return(synth(405,"Not allowed."));
        }
        return(purge);
    }

    # Pleroma MediaProxy - strip headers that will affect caching
    if (req.url ~ "^/proxy/") {
        unset req.http.Cookie;
        unset req.http.Authorization;
        unset req.http.Accept;
        return (hash);
    }

    # Strip headers that will affect caching from all other static content
    # This also permits caching of individual toots and AP Activities
    if ((req.url ~ "^/(media|static)/") ||
    (req.url ~ "(?i)\.(html|js|css|jpg|jpeg|png|gif|gz|tgz|bz2|tbz|mp3|ogg|svg|swf|ttf|pdf|woff|woff2)$"))
    {
      unset req.http.Cookie;
      unset req.http.Authorization;
      return (hash);
    }

    # Everything else should just be piped to Pleroma
    return (pipe);
}

sub vcl_backend_response {
    # gzip text content
    if (beresp.http.content-type ~ "(text|text/css|application/x-javascript|application/javascript)") {
      set beresp.do_gzip = true;
    }

    # etags are bad
    unset beresp.http.etag;

    # Don't cache objects that require authentication
    if (beresp.http.Authorization && !beresp.http.Cache-Control ~ "public") {
      set beresp.uncacheable = true;
      return (deliver);
    }

    # Default object caching of 86400s;
    set beresp.ttl = 86400s;
    # Allow serving cached content for 6h in case backend goes down
    set beresp.grace = 6h;

    # Do not cache 5xx responses
    if (beresp.status == 500 || beresp.status == 502 || beresp.status == 503 || beresp.status == 504) {
      set beresp.uncacheable = true;
      return (abandon);
    }

    # Do not cache redirects and errors
    if ((beresp.status >= 300) && (beresp.status < 500)) {
        set beresp.uncacheable = true;
        set beresp.ttl = 30s;
        return (deliver);
    }

    # Pleroma MediaProxy internally sets headers properly
    if (bereq.url ~ "^/proxy/") {
      return (deliver);
    }

    # Strip cache-restricting headers from Pleroma on static content that we want to cache
    # Also enable streaming of cached content to clients (no waiting for Varnish to complete backend fetch)
    if (bereq.url ~ "(?i)\.(js|css|jpg|jpeg|png|gif|gz|tgz|bz2|tbz|mp3|ogg|svg|swf|ttf|pdf|woff|woff2)$")
    {
      unset beresp.http.set-cookie;
      unset beresp.http.Cache-Control;
      unset beresp.http.x-request-id;
      set beresp.http.Cache-Control = "public, max-age=86400";
      set beresp.do_stream = true;
    }
}

# The synthetic response for 301 redirects
sub vcl_synth {
    if (resp.status == 750) {
      set resp.status = 301;
      set resp.http.Location = req.http.x-redir;
      return(deliver);
    }
}

# Ensure WebSockets through the pipe do not close prematurely
sub vcl_pipe {
    if (req.http.upgrade) {
        set bereq.http.upgrade = req.http.upgrade;
        set bereq.http.connection = req.http.connection;
    }
}

sub vcl_deliver {
  set resp.http.X-Frame-Options = "DENY";
  set resp.http.X-XSS-Protection = "1; mode=block";
  set resp.http.X-Content-Type-Options = "nosniff";
  set resp.http.Referrer-Policy = "same-origin";
  set resp.http.Content-Security-Policy = "default-src 'none'; base-uri 'self'; form-action 'self'; img-src 'self' data: https:; media-src 'self' https:; style-src 'self' 'unsafe-inline'; font-src 'self'; script-src 'self'; connect-src 'self' wss://" + req.http.host + "; upgrade-insecure-requests;";
  # Uncomment this only after you get HTTPS working.
  # set resp.http.Strict-Transport-Security= "max-age=31536000; includeSubDomains";
}