feat: Appwrite service

This commit is contained in:
Andras Bacsai
2022-08-15 14:58:10 +00:00
parent 3dd2a059bf
commit 8b5c7c94cd
14 changed files with 887 additions and 29 deletions

View File

@@ -0,0 +1,22 @@
-- CreateTable
CREATE TABLE "Appwrite" (
"id" TEXT NOT NULL PRIMARY KEY,
"serviceId" TEXT NOT NULL,
"opensslKeyV1" TEXT NOT NULL,
"executorSecret" TEXT NOT NULL,
"redisPassword" TEXT NOT NULL,
"mariadbHost" TEXT,
"mariadbPort" INTEGER NOT NULL DEFAULT 3306,
"mariadbUser" TEXT NOT NULL,
"mariadbPassword" TEXT NOT NULL,
"mariadbRootUser" TEXT NOT NULL,
"mariadbRootUserPassword" TEXT NOT NULL,
"mariadbDatabase" TEXT NOT NULL,
"mariadbPublicPort" INTEGER,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
CONSTRAINT "Appwrite_serviceId_fkey" FOREIGN KEY ("serviceId") REFERENCES "Service" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
);
-- CreateIndex
CREATE UNIQUE INDEX "Appwrite_serviceId_key" ON "Appwrite"("serviceId");

View File

@@ -312,30 +312,33 @@ model DatabaseSettings {
}
model Service {
id String @id @default(cuid())
id String @id @default(cuid())
name String
fqdn String?
exposePort Int?
dualCerts Boolean @default(false)
dualCerts Boolean @default(false)
type String?
version String?
destinationDockerId String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
destinationDocker DestinationDocker? @relation(fields: [destinationDockerId], references: [id])
fider Fider?
ghost Ghost?
hasura Hasura?
meiliSearch MeiliSearch?
minio Minio?
moodle Moodle?
plausibleAnalytics PlausibleAnalytics?
persistentStorage ServicePersistentStorage[]
serviceSecret ServiceSecret[]
umami Umami?
vscodeserver Vscodeserver?
wordpress Wordpress?
teams Team[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
destinationDocker DestinationDocker? @relation(fields: [destinationDockerId], references: [id])
fider Fider?
ghost Ghost?
hasura Hasura?
meiliSearch MeiliSearch?
minio Minio?
moodle Moodle?
plausibleAnalytics PlausibleAnalytics?
persistentStorage ServicePersistentStorage[]
serviceSecret ServiceSecret[]
umami Umami?
vscodeserver Vscodeserver?
wordpress Wordpress?
appwrite Appwrite?
teams Team[]
}
model PlausibleAnalytics {
@@ -491,3 +494,22 @@ model Moodle {
updatedAt DateTime @updatedAt
service Service @relation(fields: [serviceId], references: [id])
}
model Appwrite {
id String @id @default(cuid())
serviceId String @unique
opensslKeyV1 String
executorSecret String
redisPassword String
mariadbHost String?
mariadbPort Int @default(3306)
mariadbUser String
mariadbPassword String
mariadbRootUser String
mariadbRootUserPassword String
mariadbDatabase String
mariadbPublicPort Int?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
service Service @relation(fields: [serviceId], references: [id])
}

View File

@@ -17,7 +17,7 @@ import { checkContainer, removeContainer } from './docker';
import { day } from './dayjs';
import * as serviceFields from './serviceFields'
export const version = '3.3.4';
export const version = '3.4.0';
export const isDev = process.env.NODE_ENV === 'development';
const algorithm = 'aes-256-ctr';
@@ -78,6 +78,8 @@ export const include: any = {
umami: true,
hasura: true,
fider: true,
moodle: true,
appwrite: true
};
export const uniqueName = (): string => uniqueNamesGenerator(customConfig);
@@ -275,6 +277,17 @@ export const supportedServiceTypesAndVersions = [
main: 3000
}
},
{
name: 'appwrite',
fancyName: 'Appwrite',
baseImage: 'appwrite/appwrite',
images: ['mariadb:10.7', 'redis:6.2-alpine', 'appwrite/telegraf:1.4.0'],
versions: ['latest', '0.15.3'],
recommendedVersion: '0.15.3',
ports: {
main: 80
}
}
// {
// name: 'moodle',
// fancyName: 'Moodle',
@@ -596,7 +609,7 @@ export async function startTraefikProxy(id: string): Promise<void> {
if (!found) {
const { stdout: coolifyNetwork } = await executeDockerCmd({ dockerId: id, command: `docker network ls --filter 'name=coolify-infra' --no-trunc --format "{{json .}}"` })
if (!coolifyNetwork) {
await executeDockerCmd({ dockerId: id, command: `docker network create --attachable coolify-infra` })
}
@@ -1538,6 +1551,35 @@ export async function configureServiceType({
}
}
});
} else if (type === 'appwrite') {
const opensslKeyV1 = encrypt(generatePassword());
const executorSecret = encrypt(generatePassword());
const redisPassword = encrypt(generatePassword());
const mariadbHost = `${id}-mariadb`
const mariadbUser = cuid();
const mariadbPassword = encrypt(generatePassword());
const mariadbDatabase = 'appwrite';
const mariadbRootUser = cuid();
const mariadbRootUserPassword = encrypt(generatePassword());
await prisma.service.update({
where: { id },
data: {
type,
appwrite: {
create: {
opensslKeyV1,
executorSecret,
redisPassword,
mariadbHost,
mariadbUser,
mariadbPassword,
mariadbDatabase,
mariadbRootUser,
mariadbRootUserPassword
}
}
}
});
} else {
await prisma.service.update({
where: { id },
@@ -1549,6 +1591,7 @@ export async function configureServiceType({
}
export async function removeService({ id }: { id: string }): Promise<void> {
await prisma.serviceSecret.deleteMany({ where: { serviceId: id } });
await prisma.servicePersistentStorage.deleteMany({ where: { serviceId: id } });
await prisma.meiliSearch.deleteMany({ where: { serviceId: id } });
await prisma.fider.deleteMany({ where: { serviceId: id } });
@@ -1559,8 +1602,8 @@ export async function removeService({ id }: { id: string }): Promise<void> {
await prisma.minio.deleteMany({ where: { serviceId: id } });
await prisma.vscodeserver.deleteMany({ where: { serviceId: id } });
await prisma.wordpress.deleteMany({ where: { serviceId: id } });
await prisma.serviceSecret.deleteMany({ where: { serviceId: id } });
await prisma.moodle.deleteMany({ where: { serviceId: id } });
await prisma.appwrite.deleteMany({ where: { serviceId: id } });
await prisma.service.delete({ where: { id } });
}
@@ -1625,9 +1668,9 @@ export const getServiceMainPort = (service: string) => {
export function makeLabelForServices(type) {
return [
'coolify.managed=true',
`coolify.version = ${version} `,
`coolify.version = ${version}`,
`coolify.type = service`,
`coolify.service.type = ${type} `
`coolify.service.type = ${type}`
];
}
export function errorHandler({ status = 500, message = 'Unknown error.' }: { status: number, message: string | any }) {

View File

@@ -16,6 +16,7 @@ export function formatLabelsOnDocker(data) {
export async function checkContainer({ dockerId, container, remove = false }: { dockerId: string, container: string, remove?: boolean }): Promise<boolean> {
let containerFound = false;
try {
console.log('checking ', container)
const { stdout } = await executeDockerCmd({
dockerId,
command:
@@ -71,7 +72,7 @@ export async function removeContainer({
}): Promise<void> {
try {
const { stdout } = await executeDockerCmd({ dockerId, command: `docker inspect --format '{{json .State}}' ${id}` })
console.log(id)
if (JSON.parse(stdout).Running) {
await executeDockerCmd({ dockerId, command: `docker stop -t 0 ${id}` })
await executeDockerCmd({ dockerId, command: `docker rm ${id}` })

View File

@@ -469,6 +469,87 @@ export const moodle = [{
isBoolean: false,
isEncrypted: true
},
{
name: 'mariadbDatabase',
isEditable: true,
isLowerCase: false,
isNumber: false,
isBoolean: false,
isEncrypted: false
}]
export const appwrite = [{
name: 'opensslKeyV1',
isEditable: false,
isLowerCase: false,
isNumber: false,
isBoolean: false,
isEncrypted: true
},
{
name: 'executorSecret',
isEditable: false,
isLowerCase: false,
isNumber: false,
isBoolean: false,
isEncrypted: true
},
{
name: 'redisPassword',
isEditable: false,
isLowerCase: false,
isNumber: false,
isBoolean: false,
isEncrypted: true
},
{
name: 'mariadbHost',
isEditable: false,
isLowerCase: false,
isNumber: false,
isBoolean: false,
isEncrypted: false
},
{
name: 'mariadbPort',
isEditable: false,
isLowerCase: false,
isNumber: false,
isBoolean: false,
isEncrypted: false
},
{
name: 'mariadbUser',
isEditable: false,
isLowerCase: false,
isNumber: false,
isBoolean: false,
isEncrypted: false
},
{
name: 'mariadbPassword',
isEditable: false,
isLowerCase: false,
isNumber: false,
isBoolean: false,
isEncrypted: true
},
{
name: 'mariadbRootUser',
isEditable: false,
isLowerCase: false,
isNumber: false,
isBoolean: false,
isEncrypted: false
},
{
name: 'mariadbRootUserPassword',
isEditable: false,
isLowerCase: false,
isNumber: false,
isBoolean: false,
isEncrypted: true
},
{
name: 'mariadbDatabase',
isEditable: true,

View File

@@ -0,0 +1,35 @@
import { createDirectories, getServiceFromDB, getServiceImage, getServiceMainPort, makeLabelForServices } from "./common";
export async function defaultServiceConfigurations({ id, teamId }) {
const service = await getServiceFromDB({ id, teamId });
const { destinationDockerId, destinationDocker, type, serviceSecret } = service;
const network = destinationDockerId && destinationDocker.network;
const port = getServiceMainPort(type);
const { workdir } = await createDirectories({ repository: type, buildId: id });
const image = getServiceImage(type);
let secrets = [];
if (serviceSecret.length > 0) {
serviceSecret.forEach((secret) => {
secrets.push([secret.name]=secret.value);
});
}
return { ...service, network, port, workdir, image, secrets }
}
export function defaultServiceComposeConfiguration(network: string) {
return {
networks: [network],
restart: 'always',
deploy: {
restart_policy: {
condition: 'on-failure',
delay: '10s',
max_attempts: 10,
window: '120s'
}
}
}
}

View File

@@ -9,6 +9,7 @@ import cuid from 'cuid';
import type { OnlyId } from '../../../../types';
import type { ActivateWordpressFtp, CheckService, CheckServiceDomain, DeleteServiceSecret, DeleteServiceStorage, GetServiceLogs, SaveService, SaveServiceDestination, SaveServiceSecret, SaveServiceSettings, SaveServiceStorage, SaveServiceType, SaveServiceVersion, ServiceStartStop, SetWordpressSettings } from './types';
import { defaultServiceComposeConfiguration, defaultServiceConfigurations } from '../../../../lib/services';
// async function startServiceNew(request: FastifyRequest<OnlyId>) {
// try {
@@ -588,6 +589,9 @@ export async function startService(request: FastifyRequest<ServiceStartStop>) {
if (type === 'moodle') {
return await startMoodleService(request)
}
if (type === 'appwrite') {
return await startAppWriteService(request)
}
throw `Service type ${type} not supported.`
} catch (error) {
throw { status: 500, message: error?.message || error }
@@ -638,6 +642,9 @@ export async function stopService(request: FastifyRequest<ServiceStartStop>) {
if (type === 'fider') {
return await stopFiderService(request)
}
if (type === 'appwrite') {
return await stopAppWriteService(request)
}
if (type === 'moodle') {
return await stopMoodleService(request)
}
@@ -2472,7 +2479,511 @@ async function stopFiderService(request: FastifyRequest<ServiceStartStop>) {
return errorHandler({ status, message })
}
}
async function startAppWriteService(request: FastifyRequest<ServiceStartStop>) {
try {
const { id } = request.params;
const teamId = request.user.teamId;
const { version, fqdn, destinationDocker, secrets, exposePort, network, port, workdir, image, appwrite } = await defaultServiceConfigurations({ id, teamId })
let isStatsEnabled = false
if (secrets._APP_USAGE_STATS) {
isStatsEnabled = true
}
const {
opensslKeyV1,
executorSecret,
mariadbHost,
mariadbPort,
mariadbUser,
mariadbPassword,
mariadbRootUser,
mariadbRootUserPassword,
mariadbDatabase
} = appwrite;
const dockerCompose = {
[id]: {
...defaultServiceComposeConfiguration(network),
image: `${image}:${version}`,
container_name: id,
labels: makeLabelForServices('appwrite'),
...(exposePort ? { ports: [`${exposePort}:${port}`] } : {}),
"volumes": [
`${id}-uploads:/storage/uploads:rw`,
`${id}-cache:/storage/cache:rw`,
`${id}-config:/storage/config:rw`,
`${id}-certificates:/storage/certificates:rw`,
`${id}-functions:/storage/functions:rw`
],
"depends_on": [
`${id}-mariadb`,
`${id}-redis`,
],
"environment": [
"_APP_ENV=production",
"_APP_LOCALE=en",
`_APP_OPENSSL_KEY_V1=${opensslKeyV1}`,
`_APP_DOMAIN=${fqdn}`,
`_APP_DOMAIN_TARGET=${fqdn}`,
`_APP_REDIS_HOST=${id}-redis`,
"_APP_REDIS_PORT=6379",
`_APP_DB_HOST=${mariadbHost}`,
`_APP_DB_PORT=${mariadbPort}`,
`_APP_DB_SCHEMA=${mariadbDatabase}`,
`_APP_DB_USER=${mariadbUser}`,
`_APP_DB_PASS=${mariadbPassword}`,
`_APP_INFLUXDB_HOST=${id}-influxdb`,
"_APP_INFLUXDB_PORT=8806",
`_APP_EXECUTOR_SECRET=${executorSecret}`,
`_APP_EXECUTOR_HOST=http://${id}-executor/v1`,
`_APP_STATSD_HOST=${id}-telegraf`,
"_APP_STATSD_PORT=8125",
...secrets
]
},
[`${id}-realtime`]: {
...defaultServiceComposeConfiguration(network),
image: `${image}:${version}`,
container_name: `${id}-realtime`,
entrypoint: "realtime",
labels: makeLabelForServices('appwrite'),
"depends_on": [
`${id}-mariadb`,
`${id}-redis`,
],
"environment": [
"_APP_ENV=production",
`_APP_OPENSSL_KEY_V1=${opensslKeyV1}`,
`_APP_REDIS_HOST=${id}-redis`,
"_APP_REDIS_PORT=6379",
`_APP_DB_HOST=${mariadbHost}`,
`_APP_DB_PORT=${mariadbPort}`,
`_APP_DB_SCHEMA=${mariadbDatabase}`,
`_APP_DB_USER=${mariadbUser}`,
`_APP_DB_PASS=${mariadbPassword}`,
...secrets
]
},
[`${id}-worker-audits`]: {
...defaultServiceComposeConfiguration(network),
image: `${image}:${version}`,
container_name: `${id}-worker-audits`,
labels: makeLabelForServices('appwrite'),
"entrypoint": "worker-audits",
"depends_on": [
`${id}-mariadb`,
`${id}-redis`,
],
"environment": [
"_APP_ENV=production",
`_APP_OPENSSL_KEY_V1=${opensslKeyV1}`,
`_APP_REDIS_HOST=${id}-redis`,
"_APP_REDIS_PORT=6379",
`_APP_DB_HOST=${mariadbHost}`,
`_APP_DB_PORT=${mariadbPort}`,
`_APP_DB_SCHEMA=${mariadbDatabase}`,
`_APP_DB_USER=${mariadbUser}`,
`_APP_DB_PASS=${mariadbPassword}`,
...secrets
]
},
[`${id}-worker-webhooks`]: {
...defaultServiceComposeConfiguration(network),
image: `${image}:${version}`,
container_name: `${id}-worker-webhooks`,
labels: makeLabelForServices('appwrite'),
"entrypoint": "worker-webhooks",
"depends_on": [
`${id}-mariadb`,
`${id}-redis`,
],
"environment": [
"_APP_ENV=production",
`_APP_OPENSSL_KEY_V1=${opensslKeyV1}`,
`_APP_REDIS_HOST=${id}-redis`,
"_APP_REDIS_PORT=6379",
...secrets
]
},
[`${id}-worker-deletes`]: {
...defaultServiceComposeConfiguration(network),
image: `${image}:${version}`,
container_name: `${id}-worker-deletes`,
labels: makeLabelForServices('appwrite'),
"entrypoint": "worker-deletes",
"depends_on": [
`${id}-mariadb`,
`${id}-redis`,
],
"volumes": [
`${id}-uploads:/storage/uploads:rw`,
`${id}-cache:/storage/cache:rw`,
`${id}-config:/storage/config:rw`,
`${id}-certificates:/storage/certificates:rw`,
`${id}-functions:/storage/functions:rw`,
`${id}-builds:/storage/builds:rw`,
],
"environment": [
"_APP_ENV=production",
`_APP_OPENSSL_KEY_V1=${opensslKeyV1}`,
`_APP_REDIS_HOST=${id}-redis`,
"_APP_REDIS_PORT=6379",
`_APP_DB_HOST=${mariadbHost}`,
`_APP_DB_PORT=${mariadbPort}`,
`_APP_DB_SCHEMA=${mariadbDatabase}`,
`_APP_DB_USER=${mariadbUser}`,
`_APP_DB_PASS=${mariadbPassword}`,
`_APP_EXECUTOR_SECRET=${executorSecret}`,
`_APP_EXECUTOR_HOST=http://${id}-executor/v1`,
...secrets
]
},
[`${id}-worker-databases`]: {
...defaultServiceComposeConfiguration(network),
image: `${image}:${version}`,
container_name: `${id}-worker-databases`,
labels: makeLabelForServices('appwrite'),
"entrypoint": "worker-databases",
"depends_on": [
`${id}-mariadb`,
`${id}-redis`,
],
"environment": [
"_APP_ENV=production",
`_APP_OPENSSL_KEY_V1=${opensslKeyV1}`,
`_APP_REDIS_HOST=${id}-redis`,
"_APP_REDIS_PORT=6379",
`_APP_DB_HOST=${mariadbHost}`,
`_APP_DB_PORT=${mariadbPort}`,
`_APP_DB_SCHEMA=${mariadbDatabase}`,
`_APP_DB_USER=${mariadbUser}`,
`_APP_DB_PASS=${mariadbPassword}`,
...secrets
]
},
[`${id}-worker-builds`]: {
...defaultServiceComposeConfiguration(network),
image: `${image}:${version}`,
container_name: `${id}-worker-builds`,
labels: makeLabelForServices('appwrite'),
"entrypoint": "worker-builds",
"depends_on": [
`${id}-mariadb`,
`${id}-redis`,
],
"environment": [
"_APP_ENV=production",
`_APP_OPENSSL_KEY_V1=${opensslKeyV1}`,
`_APP_EXECUTOR_SECRET=${executorSecret}`,
`_APP_EXECUTOR_HOST=http://${id}-executor/v1`,
`_APP_REDIS_HOST=${id}-redis`,
"_APP_REDIS_PORT=6379",
`_APP_DB_HOST=${mariadbHost}`,
`_APP_DB_PORT=${mariadbPort}`,
`_APP_DB_SCHEMA=${mariadbDatabase}`,
`_APP_DB_USER=${mariadbUser}`,
`_APP_DB_PASS=${mariadbPassword}`,
...secrets
]
},
[`${id}-worker-certificates`]: {
...defaultServiceComposeConfiguration(network),
image: `${image}:${version}`,
container_name: `${id}-worker-certificates`,
labels: makeLabelForServices('appwrite'),
"entrypoint": "worker-certificates",
"depends_on": [
`${id}-mariadb`,
`${id}-redis`,
],
"volumes": [
`${id}-config:/storage/config:rw`,
`${id}-certificates:/storage/certificates:rw`,
],
"environment": [
"_APP_ENV=production",
`_APP_OPENSSL_KEY_V1=${opensslKeyV1}`,
`_APP_DOMAIN=${fqdn}`,
`_APP_DOMAIN_TARGET=${fqdn}`,
`_APP_REDIS_HOST=${id}-redis`,
"_APP_REDIS_PORT=6379",
`_APP_DB_HOST=${mariadbHost}`,
`_APP_DB_PORT=${mariadbPort}`,
`_APP_DB_SCHEMA=${mariadbDatabase}`,
`_APP_DB_USER=${mariadbUser}`,
`_APP_DB_PASS=${mariadbPassword}`,
...secrets
]
},
[`${id}-worker-functions`]: {
...defaultServiceComposeConfiguration(network),
image: `${image}:${version}`,
container_name: `${id}-worker-functions`,
labels: makeLabelForServices('appwrite'),
"entrypoint": "worker-functions",
"depends_on": [
`${id}-mariadb`,
`${id}-redis`,
`${id}-executor`
],
"environment": [
"_APP_ENV=production",
`_APP_OPENSSL_KEY_V1=${opensslKeyV1}`,
`_APP_REDIS_HOST=${id}-redis`,
"_APP_REDIS_PORT=6379",
`_APP_DB_HOST=${mariadbHost}`,
`_APP_DB_PORT=${mariadbPort}`,
`_APP_DB_SCHEMA=${mariadbDatabase}`,
`_APP_DB_USER=${mariadbUser}`,
`_APP_DB_PASS=${mariadbPassword}`,
`_APP_EXECUTOR_SECRET=${executorSecret}`,
`_APP_EXECUTOR_HOST=http://${id}-executor/v1`,
...secrets
]
},
[`${id}-executor`]: {
...defaultServiceComposeConfiguration(network),
image: `${image}:${version}`,
container_name: `${id}-executor`,
labels: makeLabelForServices('appwrite'),
"entrypoint": "executor",
"stop_signal": "SIGINT",
"volumes": [
`${id}-functions:/storage/functions:rw`,
`${id}-builds:/storage/builds:rw`,
"/var/run/docker.sock:/var/run/docker.sock",
"/tmp:/tmp:rw"
],
"depends_on": [
`${id}-mariadb`,
`${id}-redis`,
`${id}`
],
"environment": [
"_APP_ENV=production",
`_APP_EXECUTOR_SECRET=${executorSecret}`,
...secrets
]
},
[`${id}-worker-mails`]: {
...defaultServiceComposeConfiguration(network),
image: `${image}:${version}`,
container_name: `${id}-worker-mails`,
labels: makeLabelForServices('appwrite'),
"entrypoint": "worker-mails",
"depends_on": [
`${id}-redis`,
],
"environment": [
"_APP_ENV=production",
`_APP_OPENSSL_KEY_V1=${opensslKeyV1}`,
`_APP_REDIS_HOST=${id}-redis`,
"_APP_REDIS_PORT=6379",
...secrets
]
},
[`${id}-worker-messaging`]: {
...defaultServiceComposeConfiguration(network),
image: `${image}:${version}`,
container_name: `${id}-worker-messaging`,
labels: makeLabelForServices('appwrite'),
"entrypoint": "worker-messaging",
"depends_on": [
`${id}-redis`,
],
"environment": [
"_APP_ENV=production",
`_APP_REDIS_HOST=${id}-redis`,
"_APP_REDIS_PORT=6379",
...secrets
]
},
[`${id}-maintenance`]: {
...defaultServiceComposeConfiguration(network),
image: `${image}:${version}`,
container_name: `${id}-maintenance`,
labels: makeLabelForServices('appwrite'),
"entrypoint": "maintenance",
"depends_on": [
`${id}-redis`,
],
"environment": [
"_APP_ENV=production",
`_APP_OPENSSL_KEY_V1=${opensslKeyV1}`,
`_APP_DOMAIN=${fqdn}`,
`_APP_DOMAIN_TARGET=${fqdn}`,
`_APP_REDIS_HOST=${id}-redis`,
"_APP_REDIS_PORT=6379",
`_APP_DB_HOST=${mariadbHost}`,
`_APP_DB_PORT=${mariadbPort}`,
`_APP_DB_SCHEMA=${mariadbDatabase}`,
`_APP_DB_USER=${mariadbUser}`,
`_APP_DB_PASS=${mariadbPassword}`,
...secrets
]
},
[`${id}-schedule`]: {
...defaultServiceComposeConfiguration(network),
image: `${image}:${version}`,
container_name: `${id}-schedule`,
labels: makeLabelForServices('appwrite'),
"entrypoint": "schedule",
"depends_on": [
`${id}-redis`,
],
"environment": [
"_APP_ENV=production",
`_APP_REDIS_HOST=${id}-redis`,
"_APP_REDIS_PORT=6379",
...secrets
]
},
[`${id}-mariadb`]: {
...defaultServiceComposeConfiguration(network),
"image": "mariadb:10.7",
container_name: `${id}-mariadb`,
labels: makeLabelForServices('appwrite'),
"volumes": [
`${id}-mariadb:/var/lib/mysql:rw`
],
"environment": [
`MYSQL_ROOT_USER=${mariadbRootUser}`,
`MYSQL_ROOT_PASSWORD=${mariadbRootUserPassword}`,
`MYSQL_USER=${mariadbUser}`,
`MYSQL_PASSWORD=${mariadbPassword}`,
`MYSQL_DATABASE=${mariadbDatabase}`
],
"command": "mysqld --innodb-flush-method=fsync"
},
[`${id}-redis`]: {
...defaultServiceComposeConfiguration(network),
"image": "redis:6.2-alpine",
container_name: `${id}-redis`,
"command": `redis-server --maxmemory 512mb --maxmemory-policy allkeys-lru --maxmemory-samples 5\n`,
"volumes": [
`${id}-redis:/data:rw`
]
},
};
if (isStatsEnabled) {
dockerCompose.id.depends_on.push(`${id}-influxdb`);
dockerCompose[`${id}-usage`] = {
...defaultServiceComposeConfiguration(network),
image: `${image}:${version}`,
container_name: `${id}-usage`,
labels: makeLabelForServices('appwrite'),
"entrypoint": "usage",
"depends_on": [
`${id}-mariadb`,
`${id}-influxdb`,
],
"environment": [
"_APP_ENV=production",
`_APP_OPENSSL_KEY_V1=${opensslKeyV1}`,
`_APP_DB_HOST=${mariadbHost}`,
`_APP_DB_PORT=${mariadbPort}`,
`_APP_DB_SCHEMA=${mariadbDatabase}`,
`_APP_DB_USER=${mariadbUser}`,
`_APP_DB_PASS=${mariadbPassword}`,
`_APP_INFLUXDB_HOST=${id}-influxdb`,
"_APP_INFLUXDB_PORT=8806",
`_APP_REDIS_HOST=${id}-redis`,
"_APP_REDIS_PORT=6379",
...secrets
]
}
dockerCompose[`${id}-influxdb`] = {
...defaultServiceComposeConfiguration(network),
"image": "appwrite/influxdb:1.5.0",
container_name: `${id}-influxdb`,
"volumes": [
`${id}-influxdb:/var/lib/influxdb:rw`
]
}
dockerCompose[`${id}-telegraf`] = {
...defaultServiceComposeConfiguration(network),
"image": "appwrite/telegraf:1.4.0",
container_name: `${id}-telegraf`,
"environment": [
`_APP_INFLUXDB_HOST=${id}-influxdb`,
"_APP_INFLUXDB_PORT=8806",
]
}
}
const composeFile: any = {
version: '3.8',
services: dockerCompose,
networks: {
[network]: {
external: true
}
},
volumes: {
[`${id}-uploads`]: {
name: `${id}-uploads`
},
[`${id}-cache`]: {
name: `${id}-cache`
},
[`${id}-config`]: {
name: `${id}-config`
},
[`${id}-certificates`]: {
name: `${id}-certificates`
},
[`${id}-functions`]: {
name: `${id}-functions`
},
[`${id}-builds`]: {
name: `${id}-builds`
},
[`${id}-mariadb`]: {
name: `${id}-mariadb`
},
[`${id}-redis`]: {
name: `${id}-redis`
},
[`${id}-influxdb`]: {
name: `${id}-influxdb`
}
}
};
const composeFileDestination = `${workdir}/docker-compose.yaml`;
await fs.writeFile(composeFileDestination, yaml.dump(composeFile));
await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker compose -f ${composeFileDestination} pull` })
await executeDockerCmd({ dockerId: destinationDocker.id, command: `docker compose -f ${composeFileDestination} up --build -d` })
return {}
} catch ({ status, message }) {
return errorHandler({ status, message })
}
}
async function stopAppWriteService(request: FastifyRequest<ServiceStartStop>) {
try {
// TODO: Fix async for of
const { id } = request.params;
const teamId = request.user.teamId;
const service = await getServiceFromDB({ id, teamId });
const { destinationDockerId, destinationDocker } = service;
const containers = [`${id}-mariadb`, `${id}-redis`, `${id}-influxdb`, `${id}-telegraf`, id, `${id}-realtime`, `${id}-worker-audits`, `${id}worker-webhooks`, `${id}-worker-deletes`, `${id}-worker-databases`, `${id}-worker-builds`, `${id}-worker-certificates`, `${id}-worker-functions`, `${id}-worker-mails`, `${id}-worker-messaging`, `${id}-maintenance`, `${id}-schedule`, `${id}-executor`, `${id}-usage`]
if (destinationDockerId) {
for (const container of containers) {
const found = await checkContainer({ dockerId: destinationDocker.id, container });
if (found) {
await removeContainer({ id, dockerId: destinationDocker.id });
}
}
}
return {}
} catch ({ status, message }) {
return errorHandler({ status, message })
}
}
async function startMoodleService(request: FastifyRequest<ServiceStartStop>) {
try {
const { id } = request.params;