settings.defaults.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. const Path = require('node:path')
  2. const http = require('node:http')
  3. const https = require('node:https')
  4. http.globalAgent.keepAlive = false
  5. https.globalAgent.keepAlive = false
  6. const isPreEmptible = process.env.PREEMPTIBLE === 'TRUE'
  7. module.exports = {
  8. compileSizeLimit: process.env.COMPILE_SIZE_LIMIT || '7mb',
  9. processLifespanLimitMs:
  10. parseInt(process.env.PROCESS_LIFE_SPAN_LIMIT_MS) || 60 * 60 * 24 * 1000 * 2,
  11. catchErrors: process.env.CATCH_ERRORS === 'true',
  12. path: {
  13. compilesDir:
  14. process.env.CLSI_COMPILES_PATH || Path.resolve(__dirname, '../compiles'),
  15. outputDir:
  16. process.env.CLSI_OUTPUT_PATH || Path.resolve(__dirname, '../output'),
  17. clsiCacheDir:
  18. process.env.CLSI_CACHE_PATH || Path.resolve(__dirname, '../cache'),
  19. synctexBaseDir(projectId) {
  20. return Path.join(this.compilesDir, projectId)
  21. },
  22. },
  23. internal: {
  24. clsi: {
  25. port: 3013,
  26. host: process.env.LISTEN_ADDRESS || '127.0.0.1',
  27. },
  28. load_balancer_agent: {
  29. report_load: process.env.LOAD_BALANCER_AGENT_REPORT_LOAD !== 'false',
  30. load_port: 3048,
  31. local_port: 3049,
  32. allow_maintenance:
  33. (
  34. process.env.LOAD_BALANCER_AGENT_ALLOW_MAINTENANCE ?? ''
  35. ).toLowerCase() !== 'false',
  36. },
  37. },
  38. apis: {
  39. clsi: {
  40. // Internal requests (used by tests only at the time of writing).
  41. url: `http://${process.env.CLSI_HOST || '127.0.0.1'}:3013`,
  42. // External url prefix for output files, e.g. for requests via load-balancers.
  43. outputUrlPrefix: `${process.env.ZONE ? `/zone/${process.env.ZONE}` : ''}`,
  44. },
  45. clsiPerf: {
  46. host: `${process.env.CLSI_PERF_HOST || '127.0.0.1'}:${
  47. process.env.CLSI_PERF_PORT || '3043'
  48. }`,
  49. },
  50. },
  51. smokeTest: process.env.SMOKE_TEST || false,
  52. project_cache_length_ms: 1000 * 60 * 60 * 24,
  53. parallelFileDownloads: process.env.FILESTORE_PARALLEL_FILE_DOWNLOADS || 1,
  54. filestoreDomainOveride: process.env.FILESTORE_DOMAIN_OVERRIDE,
  55. texliveImageNameOveride: process.env.TEX_LIVE_IMAGE_NAME_OVERRIDE,
  56. texliveOpenoutAny: process.env.TEXLIVE_OPENOUT_ANY,
  57. texliveMaxPrintLine: process.env.TEXLIVE_MAX_PRINT_LINE,
  58. enablePdfCaching: process.env.ENABLE_PDF_CACHING === 'true',
  59. enablePdfCachingDark: process.env.ENABLE_PDF_CACHING_DARK === 'true',
  60. pdfCachingMinChunkSize:
  61. parseInt(process.env.PDF_CACHING_MIN_CHUNK_SIZE, 10) || 1024,
  62. pdfCachingMaxProcessingTime:
  63. parseInt(process.env.PDF_CACHING_MAX_PROCESSING_TIME, 10) || 10 * 1000,
  64. pdfCachingEnableWorkerPool:
  65. process.env.PDF_CACHING_ENABLE_WORKER_POOL === 'true',
  66. pdfCachingWorkerPoolSize:
  67. parseInt(process.env.PDF_CACHING_WORKER_POOL_SIZE, 10) || 4,
  68. pdfCachingWorkerPoolBackLogLimit:
  69. parseInt(process.env.PDF_CACHING_WORKER_POOL_BACK_LOG_LIMIT, 10) || 40,
  70. compileConcurrencyLimit: isPreEmptible ? 32 : 64,
  71. }
  72. if (process.env.ALLOWED_COMPILE_GROUPS) {
  73. try {
  74. module.exports.allowedCompileGroups =
  75. process.env.ALLOWED_COMPILE_GROUPS.split(' ')
  76. } catch (error) {
  77. console.error(error, 'could not apply allowed compile group setting')
  78. process.exit(1)
  79. }
  80. }
  81. if (process.env.DOCKER_RUNNER) {
  82. let seccompProfilePath
  83. module.exports.clsi = {
  84. dockerRunner: process.env.DOCKER_RUNNER === 'true',
  85. docker: {
  86. runtime: process.env.DOCKER_RUNTIME,
  87. image:
  88. process.env.TEXLIVE_IMAGE || 'quay.io/sharelatex/texlive-full:2017.1',
  89. env: {
  90. HOME: '/tmp',
  91. CLSI: 1,
  92. },
  93. socketPath: '/var/run/docker.sock',
  94. user: process.env.TEXLIVE_IMAGE_USER || 'tex',
  95. },
  96. optimiseInDocker: true,
  97. expireProjectAfterIdleMs: 24 * 60 * 60 * 1000,
  98. checkProjectsIntervalMs: 10 * 60 * 1000,
  99. }
  100. try {
  101. // Override individual docker settings using path-based keys, e.g.:
  102. // compileGroupDockerConfigs = {
  103. // priority: { 'HostConfig.CpuShares': 100 }
  104. // beta: { 'dotted.path.here', 'value'}
  105. // }
  106. const compileGroupConfig = JSON.parse(
  107. process.env.COMPILE_GROUP_DOCKER_CONFIGS || '{}'
  108. )
  109. // Automatically clean up wordcount and synctex containers
  110. const defaultCompileGroupConfig = {
  111. wordcount: { 'HostConfig.AutoRemove': true },
  112. synctex: { 'HostConfig.AutoRemove': true },
  113. }
  114. module.exports.clsi.docker.compileGroupConfig = Object.assign(
  115. defaultCompileGroupConfig,
  116. compileGroupConfig
  117. )
  118. } catch (error) {
  119. console.error(error, 'could not apply compile group docker configs')
  120. process.exit(1)
  121. }
  122. try {
  123. seccompProfilePath = Path.resolve(__dirname, '../seccomp/clsi-profile.json')
  124. module.exports.clsi.docker.seccomp_profile = JSON.stringify(
  125. JSON.parse(require('node:fs').readFileSync(seccompProfilePath))
  126. )
  127. } catch (error) {
  128. console.error(
  129. error,
  130. `could not load seccomp profile from ${seccompProfilePath}`
  131. )
  132. process.exit(1)
  133. }
  134. if (process.env.APPARMOR_PROFILE) {
  135. try {
  136. module.exports.clsi.docker.apparmor_profile = process.env.APPARMOR_PROFILE
  137. } catch (error) {
  138. console.error(error, 'could not apply apparmor profile setting')
  139. process.exit(1)
  140. }
  141. }
  142. if (process.env.ALLOWED_IMAGES) {
  143. try {
  144. module.exports.clsi.docker.allowedImages =
  145. process.env.ALLOWED_IMAGES.split(' ')
  146. } catch (error) {
  147. console.error(error, 'could not apply allowed images setting')
  148. process.exit(1)
  149. }
  150. }
  151. module.exports.path.synctexBaseDir = () => '/compile'
  152. module.exports.path.sandboxedCompilesHostDir = process.env.COMPILES_HOST_DIR
  153. }