diff --git a/docs/configuration/nginx.md b/docs/configuration/nginx.md index 7128f7ff1..1966715f5 100644 --- a/docs/configuration/nginx.md +++ b/docs/configuration/nginx.md @@ -144,6 +144,28 @@ dokku nginx:set node-js-app proxy-read-timeout In all cases, the nginx config must be regenerated after setting the above value. +### Specifying a custom client_max_body_size + +> New as of 0.23.0 + +Users can override the default `client_max_body_size` value - which limits file uploads - via `nginx:set`. Changing this value will only apply to every `server` stanza of the default `nginx.conf.sigil`; users of custom `nginx.conf.sigil` files must update their templates to support the new value. + +```shell +dokku nginx:set node-js-app client-max-body-size 50m +``` + +The default value is empty string, which will result in nginx falling back to any configured, higher-level defaults (or `1m` if unconfigued. all numeric values _must_ have a trailing time value specified (`k` for kilobytes, `m` for megabytes). + +The default value may be set by passing an empty value for the option: + +```shell +dokku nginx:set node-js-app client-max-body-size +``` + +In all cases, the nginx config must be regenerated after setting the above value. + +Changing this value when using the php buildpack (or any other buildpack that uses an intermediary server) will require changing the value in the server config shipped with that buildpack. Consult your buildpack documentation for further details. + ### Showing the nginx config For debugging purposes, it may be useful to show the nginx config. This can be achieved via the `nginx:show-config` command. @@ -233,11 +255,11 @@ The default nginx.conf template will include everything from your apps `nginx.co include {{ .DOKKU_ROOT }}/{{ .APP }}/nginx.conf.d/*.conf; ``` -That means you can put additional configuration in separate files, for example to limit the uploaded body size to 50 megabytes, do +That means you can put additional configuration in separate files. To increase the client request header timeout, the following can be performed: ```shell mkdir /home/dokku/node-js-app/nginx.conf.d/ -echo 'client_max_body_size 50m;' > /home/dokku/node-js-app/nginx.conf.d/upload.conf +echo 'client_header_timeout 50s;' > /home/dokku/node-js-app/nginx.conf.d/timeout.conf chown dokku:dokku /home/dokku/node-js-app/nginx.conf.d/upload.conf service nginx reload ``` @@ -250,7 +272,7 @@ For PHP Buildpack users, you will also need to provide a `Procfile` and an accom Your `nginx.conf` file - not to be confused with Dokku's `nginx.conf.sigil` - would also need to be configured as shown in this example: - client_max_body_size 50m; + client_header_timeout 50s; location / { index index.php; try_files $uri $uri/ /index.php$is_args$args; diff --git a/plugins/nginx-vhosts/command-functions b/plugins/nginx-vhosts/command-functions index 99e954391..1f190c4f5 100755 --- a/plugins/nginx-vhosts/command-functions +++ b/plugins/nginx-vhosts/command-functions @@ -42,6 +42,7 @@ cmd-nginx-report-single() { "--nginx-access-log-path: $(fn-nginx-access-log-path "$APP")" "--nginx-bind-address-ipv4: $(fn-plugin-property-get-default "nginx" "$APP" "bind-address-ipv4" "")" "--nginx-bind-address-ipv6: $(fn-plugin-property-get-default "nginx" "$APP" "bind-address-ipv6" "::")" + "--nginx-client-max-body-size: $(fn-plugin-property-get-default "nginx" "$APP" "client-max-body-size" "")" "--nginx-disable-custom-config: $(fn-plugin-property-get-default "nginx" "$APP" "disable-custom-config" "false")" "--nginx-error-log-path: $(fn-nginx-error-log-path "$APP")" "--nginx-hsts: $(fn-plugin-property-get-default "nginx" "$APP" "hsts" "true")" diff --git a/plugins/nginx-vhosts/functions b/plugins/nginx-vhosts/functions index a2f04e9c8..f6cd666a0 100755 --- a/plugins/nginx-vhosts/functions +++ b/plugins/nginx-vhosts/functions @@ -63,6 +63,13 @@ fn-nginx-proxy-read-timeout() { fn-plugin-property-get-default "nginx" "$APP" "proxy-read-timeout" "60s" } +fn-nginx-client-max-body-size() { + declare desc="get the configured client max body size" + declare APP="$1" + + fn-plugin-property-get-default "nginx" "$APP" "client-max-body-size" "" +} + fn-nginx-error-log-path() { declare desc="get the configured access log path" declare APP="$1" @@ -430,6 +437,7 @@ nginx_build_config() { local NGINX_ACCESS_LOG_FORMAT="$(fn-nginx-access-log-format "$APP")" local NGINX_ACCESS_LOG_PATH="$(fn-nginx-access-log-path "$APP")" local NGINX_ERROR_LOG_PATH="$(fn-nginx-error-log-path "$APP")" + local CLIENT_MAX_BODY_SIZE="$(fn-nginx-client-max-body-size "$APP")" local PROXY_READ_TIMEOUT="$(fn-nginx-proxy-read-timeout "$APP")" local PROXY_BUFFER_SIZE="$(fn-nginx-proxy-buffer-size "$APP")" local PROXY_BUFFERING="$(fn-nginx-proxy-buffering "$APP")" @@ -486,6 +494,7 @@ nginx_build_config() { GRPC_SUPPORTED="$GRPC_SUPPORTED" DOKKU_APP_LISTEN_PORT="$DOKKU_APP_LISTEN_PORT" DOKKU_APP_LISTEN_IP="$DOKKU_APP_LISTEN_IP" APP_SSL_PATH="$APP_SSL_PATH" SSL_INUSE="$SSL_INUSE" SSL_SERVER_NAME="$SSL_SERVER_NAME" + CLIENT_MAX_BODY_SIZE="$CLIENT_MAX_BODY_SIZE" PROXY_READ_TIMEOUT="$PROXY_READ_TIMEOUT" PROXY_BUFFER_SIZE="$PROXY_BUFFER_SIZE" PROXY_BUFFERING="$PROXY_BUFFERING" diff --git a/plugins/nginx-vhosts/subcommands/set b/plugins/nginx-vhosts/subcommands/set index 681041933..34925ed99 100755 --- a/plugins/nginx-vhosts/subcommands/set +++ b/plugins/nginx-vhosts/subcommands/set @@ -9,13 +9,13 @@ cmd-nginx-set() { declare cmd="nginx:set" [[ "$1" == "$cmd" ]] && shift 1 declare APP="$1" KEY="$2" VALUE="$3" - local VALID_KEYS=("access-log-format" "access-log-path" "bind-address-ipv4" "bind-address-ipv6" "disable-custom-config" "error-log-path" "hsts" "hsts-include-subdomains" "hsts-preload" "hsts-max-age" "proxy-read-timeout" "proxy-buffer-size" "proxy-buffering" "proxy-buffers" "proxy-busy-buffers-size" "x-forwarded-for-value" "x-forwarded-port-value" "x-forwarded-proto-value") + local VALID_KEYS=("access-log-format" "access-log-path" "bind-address-ipv4" "bind-address-ipv6" "client-max-body-size" "disable-custom-config" "error-log-path" "hsts" "hsts-include-subdomains" "hsts-preload" "hsts-max-age" "proxy-read-timeout" "proxy-buffer-size" "proxy-buffering" "proxy-buffers" "proxy-busy-buffers-size" "x-forwarded-for-value" "x-forwarded-port-value" "x-forwarded-proto-value") verify_app_name "$APP" [[ -z "$KEY" ]] && dokku_log_fail "No key specified" if ! fn-in-array "$KEY" "${VALID_KEYS[@]}"; then - dokku_log_fail "Invalid key specified, valid keys include: access-log-format, access-log-path, bind-address-ipv4, bind-address-ipv6, disable-custom-config, error-log-path, hsts, hsts-include-subdomains, hsts-preload, hsts-max-age, proxy-read-timeout, proxy-buffer-size, proxy-buffering, proxy-buffers, proxy-busy-buffers-size, x-forwarded-for-value, x-forwarded-port-value, x-forwarded-proto-value" + dokku_log_fail "Invalid key specified, valid keys include: access-log-format, access-log-path, bind-address-ipv4, bind-address-ipv6, client-max-body-size, disable-custom-config, error-log-path, hsts, hsts-include-subdomains, hsts-preload, hsts-max-age, proxy-read-timeout, proxy-buffer-size, proxy-buffering, proxy-buffers, proxy-busy-buffers-size, x-forwarded-for-value, x-forwarded-port-value, x-forwarded-proto-value" fi if [[ -n "$VALUE" ]]; then diff --git a/plugins/nginx-vhosts/templates/nginx.conf.sigil b/plugins/nginx-vhosts/templates/nginx.conf.sigil index dd3fae51f..4992d9c99 100644 --- a/plugins/nginx-vhosts/templates/nginx.conf.sigil +++ b/plugins/nginx-vhosts/templates/nginx.conf.sigil @@ -38,6 +38,8 @@ server { proxy_set_header X-Forwarded-Proto {{ $.PROXY_X_FORWARDED_PROTO }}; proxy_set_header X-Request-Start $msec; } + + {{ if $.CLIENT_MAX_BODY_SIZE }}client_max_body_size {{ $.CLIENT_MAX_BODY_SIZE }};{{ end }} include {{ $.DOKKU_ROOT }}/{{ $.APP }}/nginx.conf.d/*.conf; error_page 400 401 402 403 405 406 407 408 409 410 411 412 413 414 415 416 417 418 420 422 423 424 426 428 429 431 444 449 450 451 /400-error.html; @@ -101,6 +103,8 @@ server { proxy_set_header X-Forwarded-Proto {{ $.PROXY_X_FORWARDED_PROTO }}; proxy_set_header X-Request-Start $msec; } + + {{ if $.CLIENT_MAX_BODY_SIZE }}client_max_body_size {{ $.CLIENT_MAX_BODY_SIZE }};{{ end }} include {{ $.DOKKU_ROOT }}/{{ $.APP }}/nginx.conf.d/*.conf; error_page 400 401 402 403 405 406 407 408 409 410 411 412 413 414 415 416 417 418 420 422 423 424 426 428 429 431 444 449 450 451 /400-error.html; @@ -138,6 +142,8 @@ server { location / { grpc_pass grpc://{{ $.APP }}-{{ $upstream_port }}; } + + {{ if $.CLIENT_MAX_BODY_SIZE }}client_max_body_size {{ $.CLIENT_MAX_BODY_SIZE }};{{ end }} include {{ $.DOKKU_ROOT }}/{{ $.APP }}/nginx.conf.d/*.conf; } {{ end }}{{ end }} @@ -158,6 +164,8 @@ server { location / { grpc_pass grpc://{{ $.APP }}-{{ $upstream_port }}; } + + {{ if $.CLIENT_MAX_BODY_SIZE }}client_max_body_size {{ $.CLIENT_MAX_BODY_SIZE }};{{ end }} include {{ $.DOKKU_ROOT }}/{{ $.APP }}/nginx.conf.d/*.conf; } {{ end }}{{ end }} diff --git a/tests/unit/nginx-vhosts_8.bats b/tests/unit/nginx-vhosts_8.bats index ec74d1eaa..7f6bf7009 100644 --- a/tests/unit/nginx-vhosts_8.bats +++ b/tests/unit/nginx-vhosts_8.bats @@ -16,6 +16,40 @@ teardown() { global_teardown } +@test "(nginx-vhosts) nginx:set client-max-body-size" { + deploy_app + + run /bin/bash -c "dokku nginx:set $TEST_APP client-max-body-size" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "dokku nginx:build-config $TEST_APP" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "dokku nginx:show-config $TEST_APP" + echo "output: $output" + echo "status: $status" + assert_output_contains "client_max_body_size" 0 + + run /bin/bash -c "dokku nginx:set $TEST_APP client-max-body-size 1m" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "dokku nginx:build-config $TEST_APP" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "dokku nginx:show-config $TEST_APP" + echo "output: $output" + echo "status: $status" + assert_output_contains "client_max_body_size 1m;" 1 +} + @test "(nginx-vhosts) nginx:set proxy-read-timeout" { deploy_app