-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathdocker-compose.rate_limit.yaml
More file actions
191 lines (168 loc) · 8.33 KB
/
docker-compose.rate_limit.yaml
File metadata and controls
191 lines (168 loc) · 8.33 KB
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
### docker compose overrides for rate limiting
#
# Usage:
# add the override via `-f docker-compose.rate_limit.yaml`, e.g.:
# ```
# docker compose -f docker-compose.yml -f docker-compose.rate_limit.yaml up -d
# ```
#
# Note: the custom caddy container needs to be build before use:
#
# ```
# docker compose -f docker-compose.yml -f docker-compose.rate_limit.yaml build caddy
# ```
#
# Management of API keys for premium access via the `apikeys` script in `./apikeys/apikeys.py`.
# See script header for documentation!
services:
compiler:
image: ghcr.io/astral-sh/uv:python3.13-alpine
volumes:
- ./apikeys/apikeys.py:/apikeys.py
- ${DATA_DIR:-./data}:/data
environment:
- KEYS_FILE=/data/keys.csv
- CADDY_SNIPPET=/data/apikeys.caddy
command: uv run --script /apikeys.py --compile
shutter-api:
labels:
# /check_authentication endpoint
caddy.@checkauth.path_0: "/check_authentication"
caddy.@checkauth.path_1: "/api/check_authentication"
caddy.handle: "@checkauth"
caddy.handle.handle_0: "@withApiKey"
caddy.handle.handle_0.respond: "`{\"result\": \"authenticated\"}`"
caddy.handle.handle_1: "@noApiKey"
caddy.handle.handle_1.respond: "`{\"result\": \"unauthenticated\"}`"
## Rate limiting:
# Make sure to mount compiled 'apikeys' file to this path in caddy container:
caddy.import: /etc/caddy/apikeys
caddy.handle_errors: 429
caddy.handle_errors.respond: "`{\"error\": \"Request is rate limited. See documentation! https://github.com/shutter-network/shutter-api?tab=readme-ov-file#rate-limits--authorization\", \"retry_after_seconds\": {http.response.header.Retry-After}, \"status\": {err.status_code}}`"
caddy.handle_errors.header.Content-type: "application/json"
# Rate limits unauthorized
caddy.rate_limit_0: "@noApiKey"
caddy.rate_limit_0.log_key: " "
caddy.rate_limit_0.zone_0: register_identity__unauthorized
caddy.rate_limit_0.zone_0.key: "{remote_host}"
caddy.rate_limit_0.zone_0.events: 5
caddy.rate_limit_0.zone_0.window: 1d
caddy.rate_limit_0.zone_0.match.path: "*/time/register_identity*"
caddy.rate_limit_0.zone_0.match.method: POST
caddy.rate_limit_0.zone_1: get_data_for_encryption__unauthorized
caddy.rate_limit_0.zone_1.key: "{remote_host}"
caddy.rate_limit_0.zone_1.events: 10
caddy.rate_limit_0.zone_1.window: 1d
caddy.rate_limit_0.zone_1.match.path: "*/time/get_data_for_encryption*"
caddy.rate_limit_0.zone_1.match.method: GET
caddy.rate_limit_0.zone_2: get_decryption_key__unauthorized
caddy.rate_limit_0.zone_2.key: "{remote_host}"
caddy.rate_limit_0.zone_2.events: 20
caddy.rate_limit_0.zone_2.window: 1d
caddy.rate_limit_0.zone_2.match.path: "*/time/get_decryption_key*"
caddy.rate_limit_0.zone_2.match.method: GET
caddy.rate_limit_0.zone_3: decrypt_commitment__unauthorized
caddy.rate_limit_0.zone_3.key: "{remote_host}"
caddy.rate_limit_0.zone_3.events: 10
caddy.rate_limit_0.zone_3.window: 1d
caddy.rate_limit_0.zone_3.match.path: "*/decrypt_commitment*"
caddy.rate_limit_0.zone_3.match.method: GET
caddy.rate_limit_0.zone_4: compile_event_trigger_definition__unauthorized
caddy.rate_limit_0.zone_4.key: "{remote_host}"
caddy.rate_limit_0.zone_4.events: 20
caddy.rate_limit_0.zone_4.window: 1d
caddy.rate_limit_0.zone_4.match.path: "*/event/compile_trigger_definition*"
caddy.rate_limit_0.zone_4.match.method: POST
caddy.rate_limit_0.zone_5: register_event_identity__unauthorized
caddy.rate_limit_0.zone_5.key: "{remote_host}"
caddy.rate_limit_0.zone_5.events: 5
caddy.rate_limit_0.zone_5.window: 1d
caddy.rate_limit_0.zone_5.match.path: "*/event/register_identity*"
caddy.rate_limit_0.zone_5.match.method: POST
caddy.rate_limit_0.zone_6: get_event_trigger_expiration_block__unauthorized
caddy.rate_limit_0.zone_6.key: "{remote_host}"
caddy.rate_limit_0.zone_6.events: 20
caddy.rate_limit_0.zone_6.window: 1d
caddy.rate_limit_0.zone_6.match.path: "*/event/get_trigger_expiration_block*"
caddy.rate_limit_0.zone_6.match.method: GET
caddy.rate_limit_0.zone_7: get_event_decryption_key__unauthorized
caddy.rate_limit_0.zone_7.key: "{remote_host}"
caddy.rate_limit_0.zone_7.events: 20
caddy.rate_limit_0.zone_7.window: 1d
caddy.rate_limit_0.zone_7.match.path: "*/event/get_decryption_key*"
caddy.rate_limit_0.zone_7.match.method: GET
caddy.rate_limit_0.zone_8: event_get_data_for_encryption__unauthorized
caddy.rate_limit_0.zone_8.key: "{remote_host}"
caddy.rate_limit_0.zone_8.events: 10
caddy.rate_limit_0.zone_8.window: 1d
caddy.rate_limit_0.zone_8.match.path: "*/event/get_data_for_encryption*"
caddy.rate_limit_0.zone_8.match.method: GET
# Rate limits with api key
caddy.rate_limit_1: "@withApiKey"
caddy.rate_limit_1.log_key: " "
caddy.rate_limit_1.zone_0: register_identity__authorized
caddy.rate_limit_1.zone_0.key: "{header.Authorization}"
caddy.rate_limit_1.zone_0.events: 500
caddy.rate_limit_1.zone_0.window: 1d
caddy.rate_limit_1.zone_0.match.path: "*/time/register_identity*"
caddy.rate_limit_1.zone_0.match.method: POST
caddy.rate_limit_1.zone_1: get_data_for_encryption__authorized
caddy.rate_limit_1.zone_1.key: "{header.Authorization}"
caddy.rate_limit_1.zone_1.events: 1000
caddy.rate_limit_1.zone_1.window: 1d
caddy.rate_limit_1.zone_1.match.path: "*/time/get_data_for_encryption*"
caddy.rate_limit_1.zone_1.match.method: GET
caddy.rate_limit_1.zone_2: get_decryption_key__authorized
caddy.rate_limit_1.zone_2.key: "{header.Authorization}"
caddy.rate_limit_1.zone_2.events: 2000
caddy.rate_limit_1.zone_2.window: 1d
caddy.rate_limit_1.zone_2.match.path: "*/time/get_decryption_key*"
caddy.rate_limit_1.zone_2.match.method: GET
caddy.rate_limit_1.zone_3: decrypt_commitment__authorized
caddy.rate_limit_1.zone_3.key: "{header.Authorization}"
caddy.rate_limit_1.zone_3.events: 1000
caddy.rate_limit_1.zone_3.window: 1d
caddy.rate_limit_1.zone_3.match.path: "*/decrypt_commitment*"
caddy.rate_limit_1.zone_3.match.method: GET
caddy.rate_limit_1.zone_4: compile_event_trigger_definition__authorized
caddy.rate_limit_1.zone_4.key: "{header.Authorization}"
caddy.rate_limit_1.zone_4.events: 2000
caddy.rate_limit_1.zone_4.window: 1d
caddy.rate_limit_1.zone_4.match.path: "*/event/compile_trigger_definition*"
caddy.rate_limit_1.zone_4.match.method: POST
caddy.rate_limit_1.zone_5: register_event_identity__authorized
caddy.rate_limit_1.zone_5.key: "{header.Authorization}"
caddy.rate_limit_1.zone_5.events: 500
caddy.rate_limit_1.zone_5.window: 1d
caddy.rate_limit_1.zone_5.match.path: "*/event/register_identity*"
caddy.rate_limit_1.zone_5.match.method: POST
caddy.rate_limit_1.zone_6: get_event_trigger_expiration_block__authorized
caddy.rate_limit_1.zone_6.key: "{header.Authorization}"
caddy.rate_limit_1.zone_6.events: 2000
caddy.rate_limit_1.zone_6.window: 1d
caddy.rate_limit_1.zone_6.match.path: "*/event/get_trigger_expiration_block*"
caddy.rate_limit_1.zone_6.match.method: GET
caddy.rate_limit_1.zone_7: get_event_decryption_key__authorized
caddy.rate_limit_1.zone_7.key: "{header.Authorization}"
caddy.rate_limit_1.zone_7.events: 2000
caddy.rate_limit_1.zone_7.window: 1d
caddy.rate_limit_1.zone_7.match.path: "*/event/get_decryption_key*"
caddy.rate_limit_1.zone_7.match.method: GET
caddy.rate_limit_1.zone_8: event_get_data_for_encryption__authorized
caddy.rate_limit_1.zone_8.key: "{header.Authorization}"
caddy.rate_limit_1.zone_8.events: 1000
caddy.rate_limit_1.zone_8.window: 1d
caddy.rate_limit_1.zone_8.match.path: "*/event/get_data_for_encryption*"
caddy.rate_limit_1.zone_8.match.method: GET
caddy:
build:
context: .
dockerfile: caddy/Dockerfile
image: caddy-docker-proxy-rate-limit
volumes:
- ${DATA_DIR:-./data}/apikeys.caddy:/etc/caddy/apikeys
entrypoint: /usr/bin/caddy
command: docker-proxy run
depends_on:
compiler:
condition: service_completed_successfully