From e0c84f4248c4ce159fd993a5fae80462ec4a10c4 Mon Sep 17 00:00:00 2001 From: Felipe Knorr Kuhn Date: Fri, 22 May 2026 01:09:05 +0900 Subject: [PATCH 1/8] Upgrade nginx to 1.30.1 --- docker/frontend/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/frontend/Dockerfile b/docker/frontend/Dockerfile index 6bbb2d5f32..a35f9a7612 100644 --- a/docker/frontend/Dockerfile +++ b/docker/frontend/Dockerfile @@ -13,7 +13,7 @@ RUN npm install --omit=dev --omit=optional RUN npm run build -FROM nginx:1.27.0-alpine +FROM nginx:1.30.1-alpine WORKDIR /patch From f8175b57701d10ed902e32420fe3cfdc1454dca3 Mon Sep 17 00:00:00 2001 From: Felipe Knorr Kuhn Date: Fri, 22 May 2026 04:46:02 +0900 Subject: [PATCH 2/8] Update variables_hash_max_size --- production/nginx/nginx.conf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/production/nginx/nginx.conf b/production/nginx/nginx.conf index b81321153b..1dd5b279c8 100644 --- a/production/nginx/nginx.conf +++ b/production/nginx/nginx.conf @@ -17,6 +17,8 @@ http { include __NGINX_ETC_FOLDER__/mime.types; default_type application/octet-stream; + variables_hash_max_size 4096; + # HTTP basic configuration include mempool/production/nginx/http-basic.conf; include mempool/production/nginx/http-acl.conf; From fce35111aa577967cc205fe208d67e370628442a Mon Sep 17 00:00:00 2001 From: Felipe Knorr Kuhn Date: Fri, 22 May 2026 09:42:31 +0900 Subject: [PATCH 3/8] Move the variables config to the right place --- nginx.conf | 1 + production/nginx/nginx.conf | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/nginx.conf b/nginx.conf index 670764e203..04fb11fba9 100644 --- a/nginx.conf +++ b/nginx.conf @@ -10,6 +10,7 @@ events { } http { + variables_hash_max_size 4096; sendfile on; tcp_nopush on; tcp_nodelay on; diff --git a/production/nginx/nginx.conf b/production/nginx/nginx.conf index 1dd5b279c8..b81321153b 100644 --- a/production/nginx/nginx.conf +++ b/production/nginx/nginx.conf @@ -17,8 +17,6 @@ http { include __NGINX_ETC_FOLDER__/mime.types; default_type application/octet-stream; - variables_hash_max_size 4096; - # HTTP basic configuration include mempool/production/nginx/http-basic.conf; include mempool/production/nginx/http-acl.conf; From a09e2d2c4625d3d87249b3e675f85e611d839b24 Mon Sep 17 00:00:00 2001 From: Felipe Knorr Kuhn Date: Sun, 31 May 2026 05:29:29 +0900 Subject: [PATCH 4/8] Move var to http-basic, mirror config for Docker --- docker/frontend/Dockerfile | 2 ++ docker/init.sh | 1 + http-basic.conf | 36 ++++++++++++++++++++++++++++++ nginx.conf | 38 ++------------------------------ production/nginx/http-basic.conf | 1 + 5 files changed, 42 insertions(+), 36 deletions(-) create mode 100644 http-basic.conf diff --git a/docker/frontend/Dockerfile b/docker/frontend/Dockerfile index a35f9a7612..c17f241d3d 100644 --- a/docker/frontend/Dockerfile +++ b/docker/frontend/Dockerfile @@ -21,6 +21,7 @@ COPY --from=builder /build/entrypoint.sh . COPY --from=builder /build/wait-for . COPY --from=builder /build/dist/mempool /var/www/mempool COPY --from=builder /build/nginx.conf /etc/nginx/ +COPY --from=builder /build/http-basic.conf /etc/nginx/ COPY --from=builder /build/nginx-mempool.conf /etc/nginx/conf.d/ RUN chmod +x /patch/entrypoint.sh @@ -30,6 +31,7 @@ RUN chown -R 1000:1000 /patch && chmod -R 755 /patch && \ chown -R 1000:1000 /var/cache/nginx && \ chown -R 1000:1000 /var/log/nginx && \ chown -R 1000:1000 /etc/nginx/nginx.conf && \ + chown -R 1000:1000 /etc/nginx/http-basic.conf && \ chown -R 1000:1000 /etc/nginx/conf.d && \ chown -R 1000:1000 /var/www/mempool diff --git a/docker/init.sh b/docker/init.sh index 3c5ec6aa31..f1cfd222fb 100755 --- a/docker/init.sh +++ b/docker/init.sh @@ -12,6 +12,7 @@ wget -O ./backend/GeoIP/GeoLite2-ASN.mmdb https://raw.githubusercontent.com/memp localhostIP="127.0.0.1" cp ./docker/frontend/* ./frontend cp ./nginx.conf ./frontend/ +cp ./http-basic.conf ./frontend/ cp ./nginx-mempool.conf ./frontend/ sed -i"" -e "s/${localhostIP}:80/0.0.0.0:__MEMPOOL_FRONTEND_HTTP_PORT__/g" ./frontend/nginx.conf sed -i"" -e "s/${localhostIP}/0.0.0.0/g" ./frontend/nginx.conf diff --git a/http-basic.conf b/http-basic.conf new file mode 100644 index 0000000000..90d99c65a5 --- /dev/null +++ b/http-basic.conf @@ -0,0 +1,36 @@ +variables_hash_max_size 4096; +sendfile on; +tcp_nopush on; +tcp_nodelay on; + +server_tokens off; +server_name_in_redirect off; + +access_log /var/log/nginx/access.log; +error_log /var/log/nginx/error.log; + +# reset timed out connections freeing ram +reset_timedout_connection on; +# maximum time between packets the client can pause when sending nginx any data +client_body_timeout 10s; +# maximum time the client has to send the entire header to nginx +client_header_timeout 10s; +# timeout which a single keep-alive client connection will stay open +keepalive_timeout 69s; +# maximum time between packets nginx is allowed to pause when sending the client data +send_timeout 69s; + +# number of requests per connection, does not affect SPDY +keepalive_requests 1337; + +# enable gzip compression +gzip on; +gzip_vary on; +gzip_comp_level 6; +gzip_min_length 1000; +gzip_proxied expired no-cache no-store private auth; +# text/html is always compressed by gzip module +gzip_types application/javascript application/json application/ld+json application/manifest+json application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard; + +# limit request body size +client_max_body_size 10m; diff --git a/nginx.conf b/nginx.conf index 04fb11fba9..c6b261cb0a 100644 --- a/nginx.conf +++ b/nginx.conf @@ -10,46 +10,12 @@ events { } http { - variables_hash_max_size 4096; - sendfile on; - tcp_nopush on; - tcp_nodelay on; - - server_tokens off; - server_name_in_redirect off; + # HTTP basic configuration + include /etc/nginx/http-basic.conf; include /etc/nginx/mime.types; default_type application/octet-stream; - access_log /var/log/nginx/access.log; - error_log /var/log/nginx/error.log; - - # reset timed out connections freeing ram - reset_timedout_connection on; - # maximum time between packets the client can pause when sending nginx any data - client_body_timeout 10s; - # maximum time the client has to send the entire header to nginx - client_header_timeout 10s; - # timeout which a single keep-alive client connection will stay open - keepalive_timeout 69s; - # maximum time between packets nginx is allowed to pause when sending the client data - send_timeout 69s; - - # number of requests per connection, does not affect SPDY - keepalive_requests 1337; - - # enable gzip compression - gzip on; - gzip_vary on; - gzip_comp_level 6; - gzip_min_length 1000; - gzip_proxied expired no-cache no-store private auth; - # text/html is always compressed by gzip module - gzip_types application/javascript application/json application/ld+json application/manifest+json application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard; - - # limit request body size - client_max_body_size 10m; - # proxy cache proxy_cache off; proxy_cache_path /var/cache/nginx keys_zone=cache:20m levels=1:2 inactive=600s max_size=500m; diff --git a/production/nginx/http-basic.conf b/production/nginx/http-basic.conf index fd5cc4b94a..8988ce74cc 100644 --- a/production/nginx/http-basic.conf +++ b/production/nginx/http-basic.conf @@ -1,4 +1,5 @@ # basics +variables_hash_max_size 4096; sendfile on; tcp_nopush on; tcp_nodelay on; From c9c3790b5db63bb57d2ec4618551206f5b27621d Mon Sep 17 00:00:00 2001 From: junderw Date: Sun, 31 May 2026 09:52:38 +0900 Subject: [PATCH 5/8] feat: Overwrite the esplora API for fees always --- backend/src/api/bitcoin/bitcoin.routes.ts | 41 +++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/backend/src/api/bitcoin/bitcoin.routes.ts b/backend/src/api/bitcoin/bitcoin.routes.ts index 4b8aecab80..c0fe41b7e0 100644 --- a/backend/src/api/bitcoin/bitcoin.routes.ts +++ b/backend/src/api/bitcoin/bitcoin.routes.ts @@ -38,6 +38,7 @@ class BitcoinRoutes { .get(config.MEMPOOL.API_URL_PREFIX + 'difficulty-adjustment', this.getDifficultyChange) .get(config.MEMPOOL.API_URL_PREFIX + 'fees/recommended', this.getRecommendedFees) .get(config.MEMPOOL.API_URL_PREFIX + 'fees/precise', this.getPreciseRecommendedFees) + .get(config.MEMPOOL.API_URL_PREFIX + 'fee-estimates', this.getPreciseRecommendedFeesEsploraTransformed) .get(config.MEMPOOL.API_URL_PREFIX + 'fees/mempool-blocks', this.getMempoolBlocks) .get(config.MEMPOOL.API_URL_PREFIX + 'backend-info', this.getBackendInfo) .get(config.MEMPOOL.API_URL_PREFIX + 'init-data', this.getInitData) @@ -134,6 +135,46 @@ class BitcoinRoutes { res.json(result); } + private getPreciseRecommendedFeesEsploraTransformed(req: Request, res: Response) { + if (!mempool.isInSync()) { + res.statusCode = 503; + res.send('Service Unavailable'); + return; + } + const result = feeApi.getPreciseRecommendedFee(); + + res.json({ + '1': result.fastestFee, + '2': result.fastestFee, + '3': result.halfHourFee, + '4': result.halfHourFee, + '5': result.halfHourFee, + '6': result.hourFee, + '7': result.hourFee, + '8': result.hourFee, + '9': result.hourFee, + '10': result.hourFee, + '11': result.hourFee, + '12': result.hourFee, + '13': result.hourFee, + '14': result.hourFee, + '15': result.hourFee, + '16': result.hourFee, + '17': result.hourFee, + '18': result.hourFee, + '19': result.hourFee, + '20': result.hourFee, + '21': result.hourFee, + '22': result.hourFee, + '23': result.hourFee, + '24': result.hourFee, + '25': result.hourFee, + '144': result.economyFee, + '504': result.economyFee, + '1008': result.minimumFee, + }); + } + private getMempoolBlocks(req: Request, res: Response) { try { const result = mempoolBlocks.getMempoolBlocks(); From 2f70d4e59e01e7a2fb1754a1bee0e91df7f47691 Mon Sep 17 00:00:00 2001 From: junderw Date: Sun, 31 May 2026 10:06:30 +0900 Subject: [PATCH 6/8] Add nginx proxy to fee-estimates --- production/nginx/location-api.conf | 6 ++++++ production/nginx/location-signet-api.conf | 6 ++++++ production/nginx/location-testnet-api.conf | 6 ++++++ production/nginx/location-testnet4-api.conf | 6 ++++++ 4 files changed, 24 insertions(+) diff --git a/production/nginx/location-api.conf b/production/nginx/location-api.conf index c7fabfb696..686b80dca9 100644 --- a/production/nginx/location-api.conf +++ b/production/nginx/location-api.conf @@ -50,6 +50,12 @@ location /api/v1 { # esplora # ########### +# route /api/fee-estimates to mempool backend instead of esplora +location = /api/fee-estimates { + rewrite ^/api/(.*) /api/v1/$1 break; + try_files /dev/null @mempool-api-v1-cache-hot; +} + # it's ok to cache blockchain data "forever", so we do 30d location /api/block/ { rewrite ^/api/(.*) /$1 break; diff --git a/production/nginx/location-signet-api.conf b/production/nginx/location-signet-api.conf index d3292b424a..c184c42729 100644 --- a/production/nginx/location-signet-api.conf +++ b/production/nginx/location-signet-api.conf @@ -42,6 +42,12 @@ location /signet/api/v1 { # esplora # ########### +# route /signet/api/fee-estimates to mempool backend instead of esplora +location = /signet/api/fee-estimates { + rewrite ^/signet/api/(.*) /api/v1/$1 break; + try_files /dev/null @mempool-signet-api-v1-cache-normal; +} + # it's ok to cache blockchain data "forever", so we do 30d location /signet/api/block/ { rewrite ^/signet/api/(.*) /$1 break; diff --git a/production/nginx/location-testnet-api.conf b/production/nginx/location-testnet-api.conf index d43a51ce51..4b9433bb81 100644 --- a/production/nginx/location-testnet-api.conf +++ b/production/nginx/location-testnet-api.conf @@ -42,6 +42,12 @@ location /testnet/api/v1 { # esplora # ########### +# route /testnet/api/fee-estimates to mempool backend instead of esplora +location = /testnet/api/fee-estimates { + rewrite ^/testnet/api/(.*) /api/v1/$1 break; + try_files /dev/null @mempool-testnet-api-v1-cache-normal; +} + # it's ok to cache blockchain data "forever", so we do 30d location /testnet/api/block/ { rewrite ^/testnet/api/(.*) /$1 break; diff --git a/production/nginx/location-testnet4-api.conf b/production/nginx/location-testnet4-api.conf index 1df5023179..11600d9e2c 100644 --- a/production/nginx/location-testnet4-api.conf +++ b/production/nginx/location-testnet4-api.conf @@ -42,6 +42,12 @@ location /testnet4/api/v1 { # esplora # ########### +# route /testnet4/api/fee-estimates to mempool backend instead of esplora +location = /testnet4/api/fee-estimates { + rewrite ^/testnet4/api/(.*) /api/v1/$1 break; + try_files /dev/null @mempool-testnet4-api-v1-cache-normal; +} + # it's ok to cache blockchain data "forever", so we do 30d location /testnet4/api/block/ { rewrite ^/testnet4/api/(.*) /$1 break; From ee55d33e6a80b3ac569280ddf66dda9eddb52891 Mon Sep 17 00:00:00 2001 From: junderw Date: Sun, 31 May 2026 10:22:05 +0900 Subject: [PATCH 7/8] Deprecation warning to esplora fees --- backend/src/api/bitcoin/bitcoin.routes.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/src/api/bitcoin/bitcoin.routes.ts b/backend/src/api/bitcoin/bitcoin.routes.ts index c0fe41b7e0..050af99fde 100644 --- a/backend/src/api/bitcoin/bitcoin.routes.ts +++ b/backend/src/api/bitcoin/bitcoin.routes.ts @@ -144,6 +144,7 @@ class BitcoinRoutes { const result = feeApi.getPreciseRecommendedFee(); res.json({ + 'warning': 'This endpoint is deprecated and will be removed in a future release. Please use /api/v1/fees/precise instead.', '1': result.fastestFee, '2': result.fastestFee, '3': result.halfHourFee, From 5cbfb7f53851980bb8369e70fd6689220774bf23 Mon Sep 17 00:00:00 2001 From: wiz Date: Sun, 31 May 2026 10:24:48 +0900 Subject: [PATCH 8/8] ops: Add /api/fee-estimates to cache heater --- production/nginx-cache-heater | 1 + 1 file changed, 1 insertion(+) diff --git a/production/nginx-cache-heater b/production/nginx-cache-heater index e6dea270a3..f0d1db1ca7 100755 --- a/production/nginx-cache-heater +++ b/production/nginx-cache-heater @@ -8,6 +8,7 @@ heat() } heatURLs=( + '/api/fee-estimates' '/api/v1/fees/recommended' '/api/v1/accelerations' )