Skip to content

Conversation

@Bhav-ikkk
Copy link

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

Copilot AI review requested due to automatic review settings December 23, 2025 12:50
@algora-pbc algora-pbc bot added the 🙋 Bounty claim Issues or PRs that have a Bounty ready to be claimed. label Dec 23, 2025
Copy link

Copilot AI left a 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_timeout column to all database tables via migration
  • Updated nginx stream configuration to apply timeout directives (proxy_connect_timeout and proxy_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"
Copy link

Copilot AI Dec 23, 2025

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.

Suggested change
<x-forms.input placeholder="5432" disabled="{{ $isPublic }}" id="publicPort" label="Public Port"
<x-forms.input placeholder="6379" disabled="{{ $isPublic }}" id="publicPort" label="Public Port"

Copilot uses AI. Check for mistakes.
<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"
Copy link

Copilot AI Dec 23, 2025

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.

Suggested change
<x-forms.input placeholder="5432" disabled="{{ $isPublic }}" id="publicPort" label="Public Port"
<x-forms.input placeholder="6379" disabled="{{ $isPublic }}" id="publicPort" label="Public Port"

Copilot uses AI. Check for mistakes.
'portsMappings' => 'nullable',
'isPublic' => 'nullable|boolean',
'publicPort' => 'nullable|integer',
'publicProxyTimeout' => 'nullable|string',
Copy link

Copilot AI Dec 23, 2025

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.

Copilot uses AI. Check for mistakes.
'portsMappings' => 'nullable',
'isPublic' => 'nullable|boolean',
'publicPort' => 'nullable|integer',
'publicProxyTimeout' => 'nullable|string',
Copy link

Copilot AI Dec 23, 2025

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.

Copilot uses AI. Check for mistakes.
'portsMappings' => 'nullable|string',
'isPublic' => 'nullable|boolean',
'publicPort' => 'nullable|integer',
'publicProxyTimeout' => 'nullable|string',
Copy link

Copilot AI Dec 23, 2025

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.

Copilot uses AI. Check for mistakes.
'portsMappings' => 'nullable|string',
'isPublic' => 'nullable|boolean',
'publicPort' => 'nullable|integer',
'publicProxyTimeout' => 'nullable|string',
Copy link

Copilot AI Dec 23, 2025

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.

Copilot uses AI. Check for mistakes.
<x-forms.checkbox instantSave id="isPublic" label="Make it publicly available"
canGate="update" :canResource="$database" />
</div>
<x-forms.input placeholder="5432" disabled="{{ $isPublic }}"
Copy link

Copilot AI Dec 23, 2025

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.

Suggested change
<x-forms.input placeholder="5432" disabled="{{ $isPublic }}"
<x-forms.input placeholder="6379" disabled="{{ $isPublic }}"

Copilot uses AI. Check for mistakes.
'portsMappings' => 'nullable',
'isPublic' => 'nullable|boolean',
'publicPort' => 'nullable|integer',
'publicProxyTimeout' => 'nullable|string',
Copy link

Copilot AI Dec 23, 2025

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.

Suggested change
'publicProxyTimeout' => 'nullable|string',
'publicProxyTimeout' => 'nullable|string|regex:/^(0|\d+[smhd])$/',

Copilot uses AI. Check for mistakes.
</div>
<x-forms.input placeholder="5432" disabled="{{ $isPublic }}"
id="publicPort" label="Public Port" canGate="update" :canResource="$database" />
<x-forms.input placeholder="0" id="publicProxyTimeout"
Copy link

Copilot AI Dec 23, 2025

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.

Copilot uses AI. Check for mistakes.
'portsMappings' => 'nullable',
'isPublic' => 'nullable|boolean',
'publicPort' => 'nullable|integer',
'publicProxyTimeout' => 'nullable|string',
Copy link

Copilot AI Dec 23, 2025

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.

Copilot uses AI. Check for mistakes.
Copy link

Copilot AI left a 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
@Bhav-ikkk Bhav-ikkk force-pushed the fix/database-tcp-proxy-timeout branch from 7e49084 to 6c76c1a Compare December 25, 2025 03:59
- 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🙋 Bounty claim Issues or PRs that have a Bounty ready to be claimed.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant