-
Notifications
You must be signed in to change notification settings - Fork 1
/
ghcr.io.conf.template
90 lines (77 loc) · 3.27 KB
/
ghcr.io.conf.template
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
# Read-only proxy certain organisations to ghcr.io
#
# RESOLVER:a DNS resolver for dynamically looking up redirect domains. Defaults to 127.0.0.1
# PORT: defaults to 8080, but dokku can override
# The docker cli uses the realm domain given in the www-authenticate to auth.
# So we need to re-write from ghcr.io to our proxy.
# Use a map as it is built in, even though its not a clean way to replace strings.
# Ideally would use more-headers module, but its not in the default image.
map $upstream_http_www_authenticate $auth_header {
# used to have 1 occurance of domain, now has 2. Handle both.
~(.*)ghcr.io(.*)ghcr.io(.*) $1docker-proxy.opensafely.org$2docker-proxy.opensafely.org$3;
~(.*)ghcr.io(.*) $1docker-proxy.opensafely.org$2;
}
# these need to be global, sadly
proxy_http_version 1.1; # keep alives to upstream
server {
server_name docker-proxy.opensafely.org;
root /var/www/html;
listen ${PORT};
# no buffering
proxy_buffering off;
proxy_request_buffering off;
chunked_transfer_encoding on;
# We need a resolver configured so we can dynamically look up domains when
# redirecting. We make it an env var so that we can switch it out in prod
# for the Digital Ocean resolver
resolver ${RESOLVER};
# exact match, initial query, rewrite www-authentication header
location = /v2/ {
limit_except GET { deny all; }
proxy_pass https://ghcr.io;
proxy_redirect default;
# ensure Host header and SNI domain match
proxy_ssl_server_name on;
# hide upstream header
proxy_hide_header www-authenticate;
# add our modified header
add_header Www-Authenticate $auth_header always;
}
# authentication API, just pass thru
location /token {
limit_except GET { deny all; }
proxy_pass https://ghcr.io;
proxy_redirect default;
# ensure Host header and SNI domain match
proxy_ssl_server_name on;
}
# opensafely images only, and handle redirects
location /v2/opensafely-core/ {
limit_except GET { deny all; }
proxy_pass https://ghcr.io;
# ensure Host header and SNI domain match
proxy_ssl_server_name on;
proxy_redirect default;
# ghcr.io redirects to an S3 bucket, which is not accessible from
# backends. So handle redirects to S3 here in the proxy rather than
# passing back to the client
proxy_intercept_errors on;
error_page 301 302 307 = @handle_redirect;
}
location @handle_redirect {
# set saves the initial response's Location: header
set $redirect '$upstream_http_location';
# strip the ghcr.io auth or else CDN rejects it, also stops it leaking
proxy_set_header Authorization "";
# proxy the CDN location back to the client
proxy_pass $redirect;
# ensure Host header and SNI domain match
proxy_ssl_server_name on;
}
location /v2/ {
limit_except GET { deny all; }
# 404 any other /v2/<org> paths in a way that the docker client understands
add_header 'Content-Type' 'application/json; charset=UTF-8' always;
return 404 '{ "errors": [{"code": "NAME_UNKNOWN", "message": "only opensafely repositories allowed" }] }';
}
}