A => .editorconfig +16 -0
@@ 1,16 @@
+root = true
+
+[*]
+indent_style = space
+indent_size = 2
+end_of_line = lf
+trim_trailing_spaces = true
+insert_final_newline = true
+
+# trailing spaces in markdown indicate word wrap
+[*.md]
+trim_trailing_spaces = false
+max_line_length = 80
+
+[*.json]
+insert_final_newline = false
A => .gitignore +2 -0
@@ 1,2 @@
+vendor
+composer.lock
A => README.md +7 -0
@@ 1,7 @@
+# Nginx Packagist Proxy
+
+```sh
+docker-compose run --rm nginx sh -c 'nginx -T'
+docker-compose up --detach --force-recreate nginx
+docker-compose run --rm --entrypoint ash composer -c 'time composer --no-cache -vvv require -- psr/container'
+```
A => composer.json +17 -0
@@ 1,17 @@
+{
+ "repositories": [
+ {
+ "type": "composer",
+ "url": "http://nginx/packagist.org/"
+ },
+ {
+ "packagist": false
+ }
+ ],
+ "config": {
+ "secure-http": false
+ },
+ "require": {
+ "psr/container": "^2.0"
+ }
+}<
\ No newline at end of file
A => default.conf +53 -0
@@ 1,53 @@
+proxy_cache_path /var/cache/nginx/proxy_cache levels=1:2 use_temp_path=off keys_zone=cache:10m;
+
+server {
+ listen 80;
+ server_name localhost;
+
+ proxy_cache cache;
+ proxy_cache_background_update on;
+ proxy_cache_use_stale error timeout updating;
+ proxy_cache_valid 200 201 301 302 24h;
+
+ location = /packagist.org/packages.json {
+ # Ignore the cache-control header of https://packagist.org/packages.json because it disables caching.
+ proxy_cache_valid 5m;
+ proxy_ignore_headers Cache-Control;
+
+ proxy_pass https://packagist.org/packages.json;
+
+ # Disable compression because otherwise the sub_filter module does not work.
+ proxy_set_header Accept-Encoding "";
+ sub_filter '"metadata-url":"/p2/' '"metadata-url":"/packagist.org/p2/';
+ sub_filter '"notify-batch":"https://packagist.org/' '"notify-batch":"http://$host/packagist.org/';
+ sub_filter_once on;
+ sub_filter_types application/json;
+ }
+
+ location = /packagist.org/downloads/ {
+ proxy_pass https://packagist.org/downloads/;
+ }
+
+ location /packagist.org/p2/ {
+ proxy_pass https://packagist.org/p2/;
+ # Disable compression because otherwise the sub_filter module does not work.
+ proxy_set_header Accept-Encoding "";
+ sub_filter '"url":"https://api.github.com/' '"url":"http://$host/api.github.com/';
+ sub_filter_once off;
+ sub_filter_types application/json;
+ }
+
+ location /api.github.com/ {
+ proxy_pass https://api.github.com/;
+ proxy_redirect https://codeload.github.com/ http://$host/codeload.github.com/;
+ }
+
+ location /codeload.github.com/ {
+ proxy_pass https://codeload.github.com/;
+ }
+
+ error_page 500 502 503 504 /50x.html;
+ location = /50x.html {
+ root /usr/share/nginx/html;
+ }
+}
A => docker-compose.yml +19 -0
@@ 1,19 @@
+version: "3.8"
+services:
+ nginx:
+ image: docker.io/library/nginx:1.21.4-alpine
+ networks: [ public, sandbox ]
+ volumes: [ "./default.conf:/etc/nginx/conf.d/default.conf:ro" ]
+ composer:
+ cap_drop: [ "ALL" ]
+ image: docker.io/library/composer:2.1.14
+ networks: [ sandbox ]
+ read_only: true
+ tmpfs: /tmp
+ volumes: [ "${PWD:?}:${PWD:?}:rw" ]
+ working_dir: "${PWD:?}"
+
+networks:
+ public: {}
+ sandbox:
+ internal: true