diff --git a/apps/api/src/lib/services/common.ts b/apps/api/src/lib/services/common.ts index f6174ca69..de9596317 100644 --- a/apps/api/src/lib/services/common.ts +++ b/apps/api/src/lib/services/common.ts @@ -20,7 +20,7 @@ export const includeServices: any = { glitchTip: true, searxng: true, weblate: true, - taiga: true + taiga: true, }; export async function configureServiceType({ id, @@ -350,6 +350,13 @@ export async function configureServiceType({ } } }); + } else if (type === 'trilium') { + await prisma.service.update({ + where: { id }, + data: { + type + } + }); } else { await prisma.service.update({ where: { id }, diff --git a/apps/api/src/lib/services/handlers.ts b/apps/api/src/lib/services/handlers.ts index f6aaa6be5..9c0f7019f 100644 --- a/apps/api/src/lib/services/handlers.ts +++ b/apps/api/src/lib/services/handlers.ts @@ -69,6 +69,10 @@ export async function startService(request: FastifyRequest) { if (type === 'taiga') { return await startTaigaService(request) } + if (type === 'trilium') { + return await startTriliumService(request) + } + throw `Service type ${type} not supported.` } catch (error) { throw { status: 500, message: error?.message || error } @@ -900,8 +904,8 @@ async function startMeilisearchService(request: FastifyRequest const { meiliSearch: { masterKey } } = service; - const { type, version, destinationDockerId, destinationDocker, serviceSecret, exposePort, persistentStorage } = - service; + const { type, version, destinationDockerId, destinationDocker, + serviceSecret, exposePort, persistentStorage } = service; const network = destinationDockerId && destinationDocker.network; const port = getServiceMainPort('meilisearch'); @@ -2640,3 +2644,58 @@ async function startTaigaService(request: FastifyRequest) { } } + +async function startTriliumService(request: FastifyRequest) { + try { + const { id } = request.params; + const teamId = request.user.teamId; + const service = await getServiceFromDB({ id, teamId }); + const { type, version, destinationDockerId, destinationDocker, serviceSecret, exposePort, persistentStorage } = + service; + const network = destinationDockerId && destinationDocker.network; + const port = getServiceMainPort('trilium'); + + const { workdir } = await createDirectories({ repository: type, buildId: id }); + const image = getServiceImage(type); + + const config = { + trilium: { + image: `${image}:${version}`, + volumes: [`${id}-trilium:/home/node/trilium-data`], + environmentVariables: {} + } + }; + if (serviceSecret.length > 0) { + serviceSecret.forEach((secret) => { + config.trilium.environmentVariables[secret.name] = secret.value; + }); + } + const { volumeMounts } = persistentVolumes(id, persistentStorage, config) + const composeFile: ComposeFile = { + version: '3.8', + services: { + [id]: { + container_name: id, + image: config.trilium.image, + volumes: config.trilium.volumes, + environment: config.trilium.environmentVariables, + ...(exposePort ? { ports: [`${exposePort}:${port}`] } : {}), + labels: makeLabelForServices('trilium'), + ...defaultComposeConfiguration(network), + } + }, + networks: { + [network]: { + external: true + } + }, + volumes: volumeMounts + }; + const composeFileDestination = `${workdir}/docker-compose.yaml`; + await fs.writeFile(composeFileDestination, yaml.dump(composeFile)); + await startServiceContainers(destinationDocker.id, composeFileDestination) + return {} + } catch ({ status, message }) { + return errorHandler({ status, message }) + } +} \ No newline at end of file diff --git a/apps/api/src/lib/services/supportedVersions.ts b/apps/api/src/lib/services/supportedVersions.ts index 643215105..440721976 100644 --- a/apps/api/src/lib/services/supportedVersions.ts +++ b/apps/api/src/lib/services/supportedVersions.ts @@ -233,4 +233,15 @@ export const supportedServiceTypesAndVersions = [ // main: 80 // } // }, + { + name: 'trilium', + fancyName: 'Trilium Notes', + baseImage: 'zadam/trilium', + images: [], + versions: ['latest'], + recommendedVersion: 'latest', + ports: { + main: 8080 + } + }, ]; \ No newline at end of file diff --git a/apps/ui/src/lib/components/svg/services/ServiceIcons.svelte b/apps/ui/src/lib/components/svg/services/ServiceIcons.svelte index 4cc5426b2..4130c0370 100644 --- a/apps/ui/src/lib/components/svg/services/ServiceIcons.svelte +++ b/apps/ui/src/lib/components/svg/services/ServiceIcons.svelte @@ -42,4 +42,6 @@ {:else if type === 'weblate'} +{:else if type === 'trilium'} + {/if} diff --git a/apps/ui/src/lib/components/svg/services/Trilium.svelte b/apps/ui/src/lib/components/svg/services/Trilium.svelte new file mode 100644 index 000000000..2bd749f44 --- /dev/null +++ b/apps/ui/src/lib/components/svg/services/Trilium.svelte @@ -0,0 +1,9 @@ + + +trilium logo diff --git a/apps/ui/src/lib/components/svg/services/index.ts b/apps/ui/src/lib/components/svg/services/index.ts index 22f7702c9..f73dcebd4 100644 --- a/apps/ui/src/lib/components/svg/services/index.ts +++ b/apps/ui/src/lib/components/svg/services/index.ts @@ -17,4 +17,5 @@ export { default as Appwrite } from './Appwrite.svelte'; export { default as Moodle } from './Moodle.svelte'; export { default as GlitchTip } from './GlitchTip.svelte'; export { default as Searxng } from './Searxng.svelte'; -export { default as Weblate } from './Weblate.svelte'; \ No newline at end of file +export { default as Weblate } from './Weblate.svelte'; +export { default as Trilium } from './Trilium.svelte' \ No newline at end of file diff --git a/apps/ui/src/routes/services/[id]/_ServiceLinks.svelte b/apps/ui/src/routes/services/[id]/_ServiceLinks.svelte index d68a3eae0..3c94c8d30 100644 --- a/apps/ui/src/routes/services/[id]/_ServiceLinks.svelte +++ b/apps/ui/src/routes/services/[id]/_ServiceLinks.svelte @@ -75,4 +75,8 @@ +{:else if service.type === 'trilium'} + + + {/if} diff --git a/apps/ui/static/trilium.png b/apps/ui/static/trilium.png new file mode 100644 index 000000000..249aceef3 Binary files /dev/null and b/apps/ui/static/trilium.png differ