Skip to content

Commit

Permalink
feat(settings): add settings for custom DNS servers and IPv4 resoluti…
Browse files Browse the repository at this point in the history
…on first

This PR adds settings to change the DNS servers Jellyseerr uses and to force Jellyseerr to resolve
DNS queries using IPv4 first. These settings aim to make it easier for less experienced users to fix
network errors related to DNS resolution.
  • Loading branch information
gauthier-th committed Jan 15, 2025
1 parent 5d9f613 commit 9dd84b6
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 7 deletions.
4 changes: 3 additions & 1 deletion cypress/config/settings.cypress.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
"mediaServerType": 1,
"partialRequestsEnabled": true,
"enableSpecialEpisodes": false,
"forceIpv4First": false,
"dnsServers": "",
"locale": "en"
},
"plex": {
Expand Down Expand Up @@ -177,4 +179,4 @@
"schedule": "0 0 5 * * *"
}
}
}
}
6 changes: 6 additions & 0 deletions overseerr-api.yml
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,12 @@ components:
enableSpecialEpisodes:
type: boolean
example: false
forceIpv4First:
type: boolean
example: false
dnsServers:
type: string
example: '1.1.1.1'
PlexLibrary:
type: object
properties:
Expand Down
17 changes: 12 additions & 5 deletions server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,6 @@ import path from 'path';
import swaggerUi from 'swagger-ui-express';
import YAML from 'yamljs';

if (process.env.forceIpv4First === 'true') {
dns.setDefaultResultOrder('ipv4first');
net.setDefaultAutoSelectFamily(false);
}

const API_SPEC_PATH = path.join(__dirname, '../overseerr-api.yml');

logger.info(`Starting Overseerr version ${getAppVersion()}`);
Expand Down Expand Up @@ -79,6 +74,18 @@ app
const settings = await getSettings().load();
restartFlag.initializeSettings(settings.main);

// Check if we force IPv4 first
if (process.env.forceIpv4First === 'true' || settings.main.forceIpv4First) {
dns.setDefaultResultOrder('ipv4first');
net.setDefaultAutoSelectFamily(false);
}

if (settings.main.dnsServers.trim() !== '') {
dns.setServers(
settings.main.dnsServers.split(',').map((server) => server.trim())
);
}

// Register HTTP proxy
if (settings.main.proxy.enabled) {
await createCustomProxyAgent(settings.main.proxy);
Expand Down
4 changes: 4 additions & 0 deletions server/lib/settings/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ export interface MainSettings {
mediaServerType: number;
partialRequestsEnabled: boolean;
enableSpecialEpisodes: boolean;
forceIpv4First: boolean;
dnsServers: string;
locale: string;
proxy: ProxySettings;
}
Expand Down Expand Up @@ -346,6 +348,8 @@ class Settings {
mediaServerType: MediaServerType.NOT_CONFIGURED,
partialRequestsEnabled: true,
enableSpecialEpisodes: false,
forceIpv4First: false,
dnsServers: '',
locale: 'en',
proxy: {
enabled: false,
Expand Down
4 changes: 3 additions & 1 deletion server/utils/restartFlag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ class RestartFlag {
return (
this.settings.csrfProtection !== settings.csrfProtection ||
this.settings.trustProxy !== settings.trustProxy ||
this.settings.proxy.enabled !== settings.proxy.enabled
this.settings.proxy.enabled !== settings.proxy.enabled ||
this.settings.forceIpv4First !== settings.forceIpv4First ||
this.settings.dnsServers !== settings.dnsServers
);
}
}
Expand Down
59 changes: 59 additions & 0 deletions src/components/Settings/SettingsMain/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ const messages = defineMessages('components.Settings.SettingsMain', {
validationApplicationUrlTrailingSlash: 'URL must not end in a trailing slash',
partialRequestsEnabled: 'Allow Partial Series Requests',
enableSpecialEpisodes: 'Allow Special Episodes Requests',
forceIpv4First: 'IPv4 Resolution First',
forceIpv4FirstTip:
'Force Jellyseerr to resolve IPv4 addresses first instead of IPv6',
dnsServers: 'Custom DNS Servers',
dnsServersTip:
'Comma-separated list of custom DNS servers, e.g. "1.1.1.1,[2606:4700:4700::1111]"',
locale: 'Display Language',
proxyEnabled: 'HTTP(S) Proxy',
proxyHostname: 'Proxy Hostname',
Expand Down Expand Up @@ -160,6 +166,8 @@ const SettingsMain = () => {
streamingRegion: data?.streamingRegion || 'US',
partialRequestsEnabled: data?.partialRequestsEnabled,
enableSpecialEpisodes: data?.enableSpecialEpisodes,
forceIpv4First: data?.forceIpv4First,
dnsServers: data?.dnsServers,
trustProxy: data?.trustProxy,
cacheImages: data?.cacheImages,
proxyEnabled: data?.proxy?.enabled,
Expand Down Expand Up @@ -191,6 +199,8 @@ const SettingsMain = () => {
originalLanguage: values.originalLanguage,
partialRequestsEnabled: values.partialRequestsEnabled,
enableSpecialEpisodes: values.enableSpecialEpisodes,
forceIpv4First: values.forceIpv4First,
dnsServers: values.dnsServers,
trustProxy: values.trustProxy,
cacheImages: values.cacheImages,
proxy: {
Expand Down Expand Up @@ -524,6 +534,55 @@ const SettingsMain = () => {
/>
</div>
</div>
<div className="form-row">
<label htmlFor="forceIpv4First" className="checkbox-label">
<span className="mr-2">
{intl.formatMessage(messages.forceIpv4First)}
</span>
<SettingsBadge badgeType="advanced" className="mr-2" />
<SettingsBadge badgeType="restartRequired" />
<span className="label-tip">
{intl.formatMessage(messages.forceIpv4FirstTip)}
</span>
</label>
<div className="form-input-area">
<Field
type="checkbox"
id="forceIpv4First"
name="forceIpv4First"
onChange={() => {
setFieldValue('forceIpv4First', !values.forceIpv4First);
}}
/>
</div>
</div>
<div className="form-row">
<label htmlFor="dnsServers" className="checkbox-label">
<span className="mr-2">
{intl.formatMessage(messages.dnsServers)}
</span>
<SettingsBadge badgeType="advanced" className="mr-2" />
<SettingsBadge badgeType="restartRequired" />
<span className="label-tip">
{intl.formatMessage(messages.dnsServersTip)}
</span>
</label>
<div className="form-input-area">
<div className="form-input-field">
<Field
id="dnsServers"
name="dnsServers"
type="text"
inputMode="url"
/>
</div>
{errors.dnsServers &&
touched.dnsServers &&
typeof errors.dnsServers === 'string' && (
<div className="error">{errors.dnsServers}</div>
)}
</div>
</div>
<div className="form-row">
<label htmlFor="proxyEnabled" className="checkbox-label">
<span className="mr-2">
Expand Down
5 changes: 5 additions & 0 deletions src/i18n/locale/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@
"components.Login.initialsigningin": "Connecting…",
"components.Login.invalidurlerror": "Unable to connect to {mediaServerName} server.",
"components.Login.loginerror": "Something went wrong while trying to sign in.",
"components.Login.noadminerror": "No admin user found on the server.",
"components.Login.password": "Password",
"components.Login.port": "Port",
"components.Login.save": "Add",
Expand Down Expand Up @@ -919,7 +920,11 @@
"components.Settings.SettingsMain.csrfProtectionTip": "Set external API access to read-only (requires HTTPS)",
"components.Settings.SettingsMain.discoverRegion": "Discover Region",
"components.Settings.SettingsMain.discoverRegionTip": "Filter content by regional availability",
"components.Settings.SettingsMain.dnsServers": "Custom DNS Servers",
"components.Settings.SettingsMain.dnsServersTip": "Comma-separated list of custom DNS servers, e.g. \"1.1.1.1,[2606:4700:4700::1111]\"",
"components.Settings.SettingsMain.enableSpecialEpisodes": "Allow Special Episodes Requests",
"components.Settings.SettingsMain.forceIpv4First": "IPv4 Resolution First",
"components.Settings.SettingsMain.forceIpv4FirstTip": "Force Jellyseerr to resolve IPv4 addresses first instead of IPv6",
"components.Settings.SettingsMain.general": "General",
"components.Settings.SettingsMain.generalsettings": "General Settings",
"components.Settings.SettingsMain.generalsettingsDescription": "Configure global and default settings for Jellyseerr.",
Expand Down

0 comments on commit 9dd84b6

Please sign in to comment.