-
-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Fix: Add configurable timeout for database TCP proxy (#7743) #7748
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: v4.x
Are you sure you want to change the base?
Fix: Add configurable timeout for database TCP proxy (#7743) #7748
Conversation
…nute timeout on long queries
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR adds a configurable timeout setting for database TCP proxy connections to address timeout issues with long-running database queries. The feature allows users to set custom timeouts (like "30m", "2h", "7d") or use unlimited timeout (default "0" which translates to 7 days in nginx), with backwards compatibility for existing databases.
- Added
public_proxy_timeoutcolumn to all database tables via migration - Updated nginx stream configuration to apply timeout directives (
proxy_connect_timeoutandproxy_timeout) - Added UI input fields for timeout configuration across all 8 database type settings pages
Reviewed changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated 16 comments.
Show a summary per file
| File | Description |
|---|---|
| database/migrations/2025_12_23_164933_add_public_proxy_timeout_to_databases.php | Migration adding public_proxy_timeout column with default value "0" to all 9 database tables (8 standalone + service_databases) |
| app/Actions/Database/StartDatabaseProxy.php | Modified nginx configuration generation to include proxy_connect_timeout and proxy_timeout directives using the timeout value (defaults to 7 days for unlimited) |
| app/Livewire/Project/Database/Redis/General.php | Added publicProxyTimeout property, validation rule, and syncData handling |
| app/Livewire/Project/Database/Postgresql/General.php | Added publicProxyTimeout property, validation rule, and syncData handling |
| app/Livewire/Project/Database/Mysql/General.php | Added publicProxyTimeout property, validation rule, and syncData handling |
| app/Livewire/Project/Database/Mongodb/General.php | Added publicProxyTimeout property, validation rule, and syncData handling |
| app/Livewire/Project/Database/Mariadb/General.php | Added publicProxyTimeout property, validation rule, and syncData handling |
| app/Livewire/Project/Database/Keydb/General.php | Added publicProxyTimeout property, validation rule, and syncData handling |
| app/Livewire/Project/Database/Dragonfly/General.php | Added publicProxyTimeout property, validation rule, and syncData handling |
| app/Livewire/Project/Database/Clickhouse/General.php | Added publicProxyTimeout property, validation rule, and syncData handling |
| resources/views/livewire/project/database/redis/general.blade.php | Added Public Proxy Timeout input field with helper text explaining usage |
| resources/views/livewire/project/database/postgresql/general.blade.php | Added Public Proxy Timeout input field with helper text explaining usage |
| resources/views/livewire/project/database/mysql/general.blade.php | Added Public Proxy Timeout input field with helper text explaining usage |
| resources/views/livewire/project/database/mongodb/general.blade.php | Added Public Proxy Timeout input field with helper text explaining usage |
| resources/views/livewire/project/database/mariadb/general.blade.php | Added Public Proxy Timeout input field with helper text explaining usage |
| resources/views/livewire/project/database/keydb/general.blade.php | Added Public Proxy Timeout input field with helper text explaining usage |
| resources/views/livewire/project/database/dragonfly/general.blade.php | Added Public Proxy Timeout input field with helper text explaining usage |
| resources/views/livewire/project/database/clickhouse/general.blade.php | Added Public Proxy Timeout input field with helper text explaining usage |
| <x-forms.checkbox instantSave id="isPublic" label="Make it publicly available" canGate="update" | ||
| :canResource="$database" /> | ||
| </div> | ||
| <x-forms.input placeholder="5432" disabled="{{ $isPublic }}" id="publicPort" label="Public Port" |
Copilot
AI
Dec 23, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The placeholder value "5432" is PostgreSQL's default port, which is incorrect for KeyDB (default port 6379). For consistency and clarity, consider using "0" as the placeholder since that's the actual default value for this timeout field, or remove the placeholder entirely as it's already specified in the helper text.
| <x-forms.input placeholder="5432" disabled="{{ $isPublic }}" id="publicPort" label="Public Port" | |
| <x-forms.input placeholder="6379" disabled="{{ $isPublic }}" id="publicPort" label="Public Port" |
| <x-forms.checkbox instantSave id="isPublic" label="Make it publicly available" canGate="update" | ||
| :canResource="$database" /> | ||
| </div> | ||
| <x-forms.input placeholder="5432" disabled="{{ $isPublic }}" id="publicPort" label="Public Port" |
Copilot
AI
Dec 23, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The placeholder value "5432" is PostgreSQL's default port, which is incorrect for Dragonfly (default port 6379). For consistency and clarity, consider using "0" as the placeholder since that's the actual default value for this timeout field, or remove the placeholder entirely as it's already specified in the helper text.
| <x-forms.input placeholder="5432" disabled="{{ $isPublic }}" id="publicPort" label="Public Port" | |
| <x-forms.input placeholder="6379" disabled="{{ $isPublic }}" id="publicPort" label="Public Port" |
| 'portsMappings' => 'nullable', | ||
| 'isPublic' => 'nullable|boolean', | ||
| 'publicPort' => 'nullable|integer', | ||
| 'publicProxyTimeout' => 'nullable|string', |
Copilot
AI
Dec 23, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The timeout value is used directly in the nginx configuration without validation of the format. Consider adding validation to ensure the value matches the expected nginx time format (e.g., using a regex pattern like '/^(0|\d+[smhd])$/' for values like '30m', '2h', '7d') to prevent invalid nginx configurations that could break the proxy.
| 'portsMappings' => 'nullable', | ||
| 'isPublic' => 'nullable|boolean', | ||
| 'publicPort' => 'nullable|integer', | ||
| 'publicProxyTimeout' => 'nullable|string', |
Copilot
AI
Dec 23, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The timeout value is used directly in the nginx configuration without validation of the format. Consider adding validation to ensure the value matches the expected nginx time format (e.g., using a regex pattern like '/^(0|\d+[smhd])$/' for values like '30m', '2h', '7d') to prevent invalid nginx configurations that could break the proxy.
| 'portsMappings' => 'nullable|string', | ||
| 'isPublic' => 'nullable|boolean', | ||
| 'publicPort' => 'nullable|integer', | ||
| 'publicProxyTimeout' => 'nullable|string', |
Copilot
AI
Dec 23, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The timeout value is used directly in the nginx configuration without validation of the format. Consider adding validation to ensure the value matches the expected nginx time format (e.g., using a regex pattern like '/^(0|\d+[smhd])$/' for values like '30m', '2h', '7d') to prevent invalid nginx configurations that could break the proxy.
| 'portsMappings' => 'nullable|string', | ||
| 'isPublic' => 'nullable|boolean', | ||
| 'publicPort' => 'nullable|integer', | ||
| 'publicProxyTimeout' => 'nullable|string', |
Copilot
AI
Dec 23, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The timeout value is used directly in the nginx configuration without validation of the format. Consider adding validation to ensure the value matches the expected nginx time format (e.g., using a regex pattern like '/^(0|\d+[smhd])$/' for values like '30m', '2h', '7d') to prevent invalid nginx configurations that could break the proxy.
| <x-forms.checkbox instantSave id="isPublic" label="Make it publicly available" | ||
| canGate="update" :canResource="$database" /> | ||
| </div> | ||
| <x-forms.input placeholder="5432" disabled="{{ $isPublic }}" |
Copilot
AI
Dec 23, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The placeholder value "5432" is PostgreSQL's default port, which is incorrect for Redis. For consistency and clarity, consider using "0" as the placeholder since that's the actual default value for this timeout field, or remove the placeholder entirely as it's already specified in the helper text.
| <x-forms.input placeholder="5432" disabled="{{ $isPublic }}" | |
| <x-forms.input placeholder="6379" disabled="{{ $isPublic }}" |
| 'portsMappings' => 'nullable', | ||
| 'isPublic' => 'nullable|boolean', | ||
| 'publicPort' => 'nullable|integer', | ||
| 'publicProxyTimeout' => 'nullable|string', |
Copilot
AI
Dec 23, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The timeout value is used directly in the nginx configuration without validation of the format. Consider adding validation to ensure the value matches the expected nginx time format (e.g., using a regex pattern like '/^(0|\d+[smhd])$/' for values like '30m', '2h', '7d') to prevent invalid nginx configurations that could break the proxy.
| 'publicProxyTimeout' => 'nullable|string', | |
| 'publicProxyTimeout' => 'nullable|string|regex:/^(0|\d+[smhd])$/', |
| </div> | ||
| <x-forms.input placeholder="5432" disabled="{{ $isPublic }}" | ||
| id="publicPort" label="Public Port" canGate="update" :canResource="$database" /> | ||
| <x-forms.input placeholder="0" id="publicProxyTimeout" |
Copilot
AI
Dec 23, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The placeholder value "5432" is PostgreSQL's default port, which is incorrect for MariaDB (default port 3306). For consistency and clarity, consider using "0" as the placeholder since that's the actual default value for this timeout field, or remove the placeholder entirely as it's already specified in the helper text.
| 'portsMappings' => 'nullable', | ||
| 'isPublic' => 'nullable|boolean', | ||
| 'publicPort' => 'nullable|integer', | ||
| 'publicProxyTimeout' => 'nullable|string', |
Copilot
AI
Dec 23, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The timeout value is used directly in the nginx configuration without validation of the format. Consider adding validation to ensure the value matches the expected nginx time format (e.g., using a regex pattern like '/^(0|\d+[smhd])$/' for values like '30m', '2h', '7d') to prevent invalid nginx configurations that could break the proxy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.
- Changed public_proxy_timeout from string to integer type - Default value of 0 represents unlimited timeout (7 days) - Users can specify timeout in seconds directly - StartDatabaseProxy converts seconds to nginx time format (appends 's') - Updated all 8 database types with consistent implementation - Added number input validation (min: 0) in all components Addresses feedback from maintainer on PR for issue coollabsio#7743
7e49084 to
6c76c1a
Compare
- Add ValidNginxTimeFormat validation rule - Update database schema to support string timeout values - Fix incorrect port placeholders for all database types - Improve UX with better helper text and examples - Ensure backward compatibility with existing integer values
The Problem
When databases are exposed publicly, the TCP proxy times out after ~10 minutes due to nginx's default timeout. This prevents long-running queries (30+ minutes) from completing successfully.
The Solution
Added a configurable public_proxy_timeout field to all databases:
Default: 0 (unlimited - translates to 7 days in nginx)
Customizable: Users can set specific values like 30m, 2h, 5d
Works for: PostgreSQL, MySQL, MariaDB, MongoDB, Redis, KeyDB, Dragonfly, Clickhouse
Changes Made
Migration: Added public_proxy_timeout column to all database tables
Backend: Updated StartDatabaseProxy.php to apply timeout to nginx config
Frontend: Added timeout input field to all 8 database settings pages
How It Works
Backwards Compatible
Yes - existing databases automatically get unlimited timeout (default 0).
Demo video will be uploaded shortly.
/claim #7743