fix: add force min/max TTL in network settings
This commit is contained in:
@@ -195,6 +195,10 @@
|
||||
"bypassFilter": "",
|
||||
"bypassLocalAddresses": true
|
||||
},
|
||||
"dnsCache": true
|
||||
"dnsCache": {
|
||||
"enabled": false,
|
||||
"forceMinTtl": 0,
|
||||
"forceMaxTtl": -1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,9 +260,51 @@ components:
|
||||
csrfProtection:
|
||||
type: boolean
|
||||
example: false
|
||||
forceIpv4First:
|
||||
type: boolean
|
||||
example: false
|
||||
trustProxy:
|
||||
type: boolean
|
||||
example: true
|
||||
example: false
|
||||
proxy:
|
||||
type: object
|
||||
properties:
|
||||
enabled:
|
||||
type: boolean
|
||||
example: false
|
||||
hostname:
|
||||
type: string
|
||||
example: ''
|
||||
port:
|
||||
type: number
|
||||
example: 8080
|
||||
useSsl:
|
||||
type: boolean
|
||||
example: false
|
||||
user:
|
||||
type: string
|
||||
example: ''
|
||||
password:
|
||||
type: string
|
||||
example: ''
|
||||
bypassFilter:
|
||||
type: string
|
||||
example: ''
|
||||
bypassLocalAddresses:
|
||||
type: boolean
|
||||
example: true
|
||||
dnsCache:
|
||||
type: object
|
||||
properties:
|
||||
enabled:
|
||||
type: boolean
|
||||
example: false
|
||||
forceMinTtl:
|
||||
type: number
|
||||
example: 0
|
||||
forceMaxTtl:
|
||||
type: number
|
||||
example: -1
|
||||
PlexLibrary:
|
||||
type: object
|
||||
properties:
|
||||
|
||||
@@ -25,7 +25,7 @@ import imageproxy from '@server/routes/imageproxy';
|
||||
import { appDataPermissions } from '@server/utils/appDataVolume';
|
||||
import { getAppVersion } from '@server/utils/appVersion';
|
||||
import createCustomProxyAgent from '@server/utils/customProxyAgent';
|
||||
import dnsCache from '@server/utils/dnsCache';
|
||||
import { initializeDnsCache } from '@server/utils/dnsCache';
|
||||
import restartFlag from '@server/utils/restartFlag';
|
||||
import { getClientIp } from '@supercharge/request-ip';
|
||||
import axios from 'axios';
|
||||
@@ -83,7 +83,10 @@ app
|
||||
|
||||
// Add DNS caching
|
||||
if (settings.network.dnsCache) {
|
||||
dnsCache.initialize();
|
||||
initializeDnsCache({
|
||||
forceMinTtl: settings.network.dnsCache.forceMinTtl,
|
||||
forceMaxTtl: settings.network.dnsCache.forceMaxTtl,
|
||||
});
|
||||
}
|
||||
|
||||
// Register HTTP proxy
|
||||
|
||||
@@ -100,17 +100,6 @@ interface Quota {
|
||||
quotaDays?: number;
|
||||
}
|
||||
|
||||
export interface ProxySettings {
|
||||
enabled: boolean;
|
||||
hostname: string;
|
||||
port: number;
|
||||
useSsl: boolean;
|
||||
user: string;
|
||||
password: string;
|
||||
bypassFilter: string;
|
||||
bypassLocalAddresses: boolean;
|
||||
}
|
||||
|
||||
export interface MainSettings {
|
||||
apiKey: string;
|
||||
applicationTitle: string;
|
||||
@@ -138,12 +127,29 @@ export interface MainSettings {
|
||||
youtubeUrl: string;
|
||||
}
|
||||
|
||||
export interface ProxySettings {
|
||||
enabled: boolean;
|
||||
hostname: string;
|
||||
port: number;
|
||||
useSsl: boolean;
|
||||
user: string;
|
||||
password: string;
|
||||
bypassFilter: string;
|
||||
bypassLocalAddresses: boolean;
|
||||
}
|
||||
|
||||
export interface DnsCacheSettings {
|
||||
enabled: boolean;
|
||||
forceMinTtl?: number;
|
||||
forceMaxTtl?: number;
|
||||
}
|
||||
|
||||
export interface NetworkSettings {
|
||||
csrfProtection: boolean;
|
||||
forceIpv4First: boolean;
|
||||
trustProxy: boolean;
|
||||
proxy: ProxySettings;
|
||||
dnsCache: boolean;
|
||||
dnsCache: DnsCacheSettings;
|
||||
}
|
||||
|
||||
interface PublicSettings {
|
||||
@@ -543,7 +549,11 @@ class Settings {
|
||||
bypassFilter: '',
|
||||
bypassLocalAddresses: true,
|
||||
},
|
||||
dnsCache: false,
|
||||
dnsCache: {
|
||||
enabled: false,
|
||||
forceMinTtl: 0,
|
||||
forceMaxTtl: -1,
|
||||
},
|
||||
},
|
||||
};
|
||||
if (initialSettings) {
|
||||
|
||||
@@ -756,8 +756,8 @@ settingsRoutes.get('/cache', async (_req, res) => {
|
||||
const tmdbImageCache = await ImageProxy.getImageStats('tmdb');
|
||||
const avatarImageCache = await ImageProxy.getImageStats('avatar');
|
||||
|
||||
const stats = dnsCache.getStats();
|
||||
const entries = dnsCache.getCacheEntries();
|
||||
const stats = dnsCache?.getStats();
|
||||
const entries = dnsCache?.getCacheEntries();
|
||||
|
||||
return res.status(200).json({
|
||||
apiCaches,
|
||||
|
||||
@@ -1,9 +1,28 @@
|
||||
import logger from '@server/logger';
|
||||
import { DnsCacheManager } from 'dns-caching';
|
||||
|
||||
const dnsCache = new DnsCacheManager({
|
||||
logger: logger,
|
||||
forceMaxTtl: Number(process.env.DNS_CACHE_FORCE_MAX_TTL) || -1,
|
||||
forceMinTtl: Number(process.env.DNS_CACHE_FORCE_MIN_TTL) || 0,
|
||||
});
|
||||
let dnsCache: DnsCacheManager | undefined;
|
||||
|
||||
export function initializeDnsCache({
|
||||
forceMinTtl,
|
||||
forceMaxTtl,
|
||||
}: {
|
||||
forceMinTtl?: number;
|
||||
forceMaxTtl?: number;
|
||||
}) {
|
||||
if (dnsCache) {
|
||||
logger.warn('DNS Cache is already initialized', { label: 'DNS Cache' });
|
||||
return;
|
||||
}
|
||||
|
||||
logger.info('Initializing DNS Cache', { label: 'DNS Cache' });
|
||||
|
||||
dnsCache = new DnsCacheManager({
|
||||
logger,
|
||||
forceMinTtl: typeof forceMinTtl === 'number' ? forceMinTtl * 1000 : 0,
|
||||
forceMaxTtl: typeof forceMaxTtl === 'number' ? forceMaxTtl * 1000 : -1,
|
||||
});
|
||||
dnsCache.initialize();
|
||||
}
|
||||
|
||||
export default dnsCache;
|
||||
|
||||
@@ -50,6 +50,8 @@ const messages = defineMessages('components.Settings.SettingsNetwork', {
|
||||
'Enable caching of DNS lookups to optimize performance and avoid making unnecessary API calls',
|
||||
dnsCacheHoverTip:
|
||||
'Do NOT enable this if you are experiencing issues with DNS lookups',
|
||||
dnsCacheForceMinTtl: 'DNS Cache Minimum TTL',
|
||||
dnsCacheForceMaxTtl: 'DNS Cache Maximum TTL',
|
||||
});
|
||||
|
||||
const SettingsNetwork = () => {
|
||||
@@ -95,7 +97,9 @@ const SettingsNetwork = () => {
|
||||
initialValues={{
|
||||
csrfProtection: data?.csrfProtection,
|
||||
forceIpv4First: data?.forceIpv4First,
|
||||
dnsCache: data?.dnsCache,
|
||||
dnsCacheEnabled: data?.dnsCache.enabled,
|
||||
dnsCacheForceMinTtl: data?.dnsCache.forceMinTtl,
|
||||
dnsCacheForceMaxTtl: data?.dnsCache.forceMaxTtl,
|
||||
trustProxy: data?.trustProxy,
|
||||
proxyEnabled: data?.proxy?.enabled,
|
||||
proxyHostname: data?.proxy?.hostname,
|
||||
@@ -114,7 +118,11 @@ const SettingsNetwork = () => {
|
||||
csrfProtection: values.csrfProtection,
|
||||
forceIpv4First: values.forceIpv4First,
|
||||
trustProxy: values.trustProxy,
|
||||
dnsCache: values.dnsCache,
|
||||
dnsCache: {
|
||||
enabled: values.dnsCacheEnabled,
|
||||
forceMinTtl: values.dnsCacheForceMinTtl,
|
||||
forceMaxTtl: values.dnsCacheForceMaxTtl,
|
||||
},
|
||||
proxy: {
|
||||
enabled: values.proxyEnabled,
|
||||
hostname: values.proxyHostname,
|
||||
@@ -229,7 +237,7 @@ const SettingsNetwork = () => {
|
||||
</div>
|
||||
</div>
|
||||
<div className="form-row">
|
||||
<label htmlFor="dnsCache" className="checkbox-label">
|
||||
<label htmlFor="dnsCacheEnabled" className="checkbox-label">
|
||||
<span className="mr-2">
|
||||
{intl.formatMessage(messages.dnsCache)}
|
||||
</span>
|
||||
@@ -246,15 +254,72 @@ const SettingsNetwork = () => {
|
||||
>
|
||||
<Field
|
||||
type="checkbox"
|
||||
id="dnsCache"
|
||||
name="dnsCache"
|
||||
id="dnsCacheEnabled"
|
||||
name="dnsCacheEnabled"
|
||||
onChange={() => {
|
||||
setFieldValue('dnsCache', !values.dnsCache);
|
||||
setFieldValue(
|
||||
'dnsCacheEnabled',
|
||||
!values.dnsCacheEnabled
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
{values.dnsCacheEnabled && (
|
||||
<>
|
||||
<div className="mr-2 ml-4">
|
||||
<div className="form-row">
|
||||
<label
|
||||
htmlFor="dnsCacheForceMinTtl"
|
||||
className="checkbox-label"
|
||||
>
|
||||
{intl.formatMessage(messages.dnsCacheForceMinTtl)}
|
||||
</label>
|
||||
<div className="form-input-area">
|
||||
<div className="form-input-field">
|
||||
<Field
|
||||
id="dnsCacheForceMinTtl"
|
||||
name="dnsCacheForceMinTtl"
|
||||
type="text"
|
||||
/>
|
||||
</div>
|
||||
{errors.dnsCacheForceMinTtl &&
|
||||
touched.dnsCacheForceMinTtl &&
|
||||
typeof errors.dnsCacheForceMinTtl === 'string' && (
|
||||
<div className="error">
|
||||
{errors.dnsCacheForceMinTtl}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="form-row">
|
||||
<label
|
||||
htmlFor="dnsCacheForceMaxTtl"
|
||||
className="checkbox-label"
|
||||
>
|
||||
{intl.formatMessage(messages.dnsCacheForceMaxTtl)}
|
||||
</label>
|
||||
<div className="form-input-area">
|
||||
<div className="form-input-field">
|
||||
<Field
|
||||
id="dnsCacheForceMaxTtl"
|
||||
name="dnsCacheForceMaxTtl"
|
||||
type="text"
|
||||
/>
|
||||
</div>
|
||||
{errors.dnsCacheForceMaxTtl &&
|
||||
touched.dnsCacheForceMaxTtl &&
|
||||
typeof errors.dnsCacheForceMaxTtl === 'string' && (
|
||||
<div className="error">
|
||||
{errors.dnsCacheForceMaxTtl}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
<div className="form-row">
|
||||
<label htmlFor="proxyEnabled" className="checkbox-label">
|
||||
<span className="mr-2">
|
||||
|
||||
Reference in New Issue
Block a user