diff --git a/.gitignore b/.gitignore index 14e9d310..8354b2df 100644 --- a/.gitignore +++ b/.gitignore @@ -50,7 +50,7 @@ nohup.out .env.production.local .env config.json -apps/*/config/default.js +# apps/*/config/default.js .patreon-credentials.json install.config diff --git a/apps/bot/config/_default.js b/apps/bot/config/default.js similarity index 100% rename from apps/bot/config/_default.js rename to apps/bot/config/default.js diff --git a/apps/bot/ecosystem.config.js b/apps/bot/ecosystem.config.js index 83a0d701..60336d69 100644 --- a/apps/bot/ecosystem.config.js +++ b/apps/bot/ecosystem.config.js @@ -2,7 +2,7 @@ module.exports = { apps: [ { name: 'Craig', - script: 'dist/sharding/index.js', + script: 'dist/index.js', wait_ready: true, kill_timeout: 3000, env: { diff --git a/apps/bot/src/bot.ts b/apps/bot/src/bot.ts index 3db62b15..b93bef9d 100644 --- a/apps/bot/src/bot.ts +++ b/apps/bot/src/bot.ts @@ -93,6 +93,11 @@ if (process.env.SHARD_ID !== undefined && process.env.SHARD_COUNT !== undefined) }) }); } +if (process.env.DISCORD_APP_ID !== undefined ) { + dexareConfig.applicationID = process.env.DISCORD_APP_ID +} + + export const client = new CraigBot(dexareConfig); process.once('SIGINT', async () => { diff --git a/apps/bot/src/redis.ts b/apps/bot/src/redis.ts index 70dc2a5d..e5996db1 100644 --- a/apps/bot/src/redis.ts +++ b/apps/bot/src/redis.ts @@ -3,8 +3,8 @@ import Redis, { RedisOptions } from 'ioredis'; const redisConfig: RedisOptions = config.get('redis'); export const client = new Redis({ - host: redisConfig.host || 'localhost', - port: redisConfig.port || 6379, + host: process.env.REDIS_HOST || redisConfig.host || 'localhost', + port: process.env.REDIS_PORT ? parseInt(process.env.REDIS_PORT, 10) : (redisConfig.port || 6379), keyPrefix: redisConfig.keyPrefix || 'craig:', lazyConnect: true }); diff --git a/apps/dashboard/utils/config.ts b/apps/dashboard/utils/config.ts index 0fcdc8ac..00b7b43b 100644 --- a/apps/dashboard/utils/config.ts +++ b/apps/dashboard/utils/config.ts @@ -14,18 +14,18 @@ function validateEnv(key: keyof NodeJS.ProcessEnv, de export const config = { cookieName: 'token', - clientId: validateEnv('CLIENT_ID'), - clientSecret: validateEnv('CLIENT_SECRET'), - patreonClientId: validateEnv('PATREON_CLIENT_ID'), - patreonClientSecret: validateEnv('PATREON_CLIENT_SECRET'), - patreonWebhookSecret: validateEnv('PATREON_WEBHOOK_SECRET'), + clientId: validateEnv('CLIENT_ID',""), + clientSecret: validateEnv('CLIENT_SECRET',""), + patreonClientId: validateEnv('PATREON_CLIENT_ID',""), + patreonClientSecret: validateEnv('PATREON_CLIENT_SECRET',""), + patreonWebhookSecret: validateEnv('PATREON_WEBHOOK_SECRET',""), patreonTierMap: validateEnv('PATREON_TIER_MAP', '{}'), - googleClientId: validateEnv('GOOGLE_CLIENT_ID'), - googleClientSecret: validateEnv('GOOGLE_CLIENT_SECRET'), - microsoftClientId: validateEnv('MICROSOFT_CLIENT_ID'), - microsoftClientSecret: validateEnv('MICROSOFT_CLIENT_SECRET'), - dropboxClientId: validateEnv('DROPBOX_CLIENT_ID'), - dropboxClientSecret: validateEnv('DROPBOX_CLIENT_SECRET'), + googleClientId: validateEnv('GOOGLE_CLIENT_ID',""), + googleClientSecret: validateEnv('GOOGLE_CLIENT_SECRET',""), + microsoftClientId: validateEnv('MICROSOFT_CLIENT_ID',""), + microsoftClientSecret: validateEnv('MICROSOFT_CLIENT_SECRET',""), + dropboxClientId: validateEnv('DROPBOX_CLIENT_ID',""), + dropboxClientSecret: validateEnv('DROPBOX_CLIENT_SECRET',""), appUri: validateEnv('APP_URI', 'http://localhost:3000'), jwtSecret: validateEnv('JWT_SECRET', 'this is a development value that should be changed in production!!!!!') } as const; diff --git a/apps/ecosystem.config.js b/apps/ecosystem.config.js new file mode 100644 index 00000000..50dde512 --- /dev/null +++ b/apps/ecosystem.config.js @@ -0,0 +1,58 @@ +module.exports = { + apps: [ + { + name: 'Craig', + cwd: '/app/apps/bot', + script: 'dist/sharding/index.js', + wait_ready: true, + kill_timeout: 3000, + env: { + NODE_ENV: 'development' + }, + env_production: { + NODE_ENV: 'production' + } + }, + { + name: 'Craig Dashboard', + cwd: '/app/apps/dashboard', + script: 'npm', + args: 'start', + env: { + NODE_ENV: 'development' + }, + env_production: { + NODE_ENV: 'production' + } + }, + { + name: 'craig.horse', + cwd: '/app/apps/download', + script: 'dist/index.js', + instances: '8', + exec_mode: 'cluster', + wait_ready: true, + listen_timeout: 10000, + kill_timeout: 3000, + env: { + NODE_ENV: 'development' + }, + env_production: { + NODE_ENV: 'production' + } + }, + { + name: 'Craig Tasks', + cwd: '/app/apps/tasks', + script: 'dist/index.js', + wait_ready: true, + kill_timeout: 3000, + env: { + NODE_ENV: 'development' + }, + env_production: { + NODE_ENV: 'production' + } + } + ] + }; \ No newline at end of file diff --git a/apps/tasks/config/_default.js b/apps/tasks/config/default.js similarity index 100% rename from apps/tasks/config/_default.js rename to apps/tasks/config/default.js diff --git a/apps/tasks/src/redis.ts b/apps/tasks/src/redis.ts index 830d88c3..b579ddbe 100644 --- a/apps/tasks/src/redis.ts +++ b/apps/tasks/src/redis.ts @@ -3,8 +3,8 @@ import Redis, { RedisOptions } from 'ioredis'; const redisConfig: RedisOptions = config.get('redis'); export const client = new Redis({ - host: redisConfig.host || 'localhost', - port: redisConfig.port || 6379, + host: process.env.REDIS_HOST || redisConfig.host || 'localhost', + port: process.env.REDIS_PORT ? parseInt(process.env.REDIS_PORT, 10) : (redisConfig.port || 6379), keyPrefix: redisConfig.keyPrefix || 'craig:', lazyConnect: true }); diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 00000000..81adc5d5 --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,45 @@ +version: '3.1' +services: + db: + image: postgres + restart: always + environment: + POSTGRES_PASSWORD: demo + POSTGRES_DB: craig + POSTGRES_USER: craig + ports: + - "5432:5432" + healthcheck: + test: ["CMD-SHELL", "pg_isready -U craig"] + interval: 5s + timeout: 5s + retries: 5 + redis: + image: redis + restart: always + ports: + - "6379:6379" + craig: + build: . + ports: + - "3000:3000" + - "5029:5029" + environment: + REDIS_HOST: redis + REDIS_PORT: "6379" + DISCORD_BOT_TOKEN: "dummy" + DISCORD_APP_ID: "dummy" + CLIENT_ID: "dummy" + CLIENT_SECRET: "dummy" + DATABASE_URL: "postgresql://craig:demo@db:5432/craig?schema=public" + API_HOMEPAGE: "http://localhost:5029" + API_HOST: "0.0.0.0" + ENNUIZEL_BASE: "https://ez.craig.horse/" + NODE_ENV: 'development' + depends_on: + db: + condition: service_healthy + restart: true + redis: + condition: service_started + # command: sleep infinity \ No newline at end of file diff --git a/dockerfile b/dockerfile index caefb939..b1806509 100644 --- a/dockerfile +++ b/dockerfile @@ -1,5 +1,5 @@ # Use an official Ubuntu base image -FROM ubuntu:22.04 +FROM node:18.20.5 # Remove interactive prompts ENV DEBIAN_FRONTEND=noninteractive @@ -9,7 +9,7 @@ RUN apt-get update && \ apt-get -y upgrade && \ apt-get install -y \ # cook - make inkscape ffmpeg flac fdkaac vorbis-tools opus-tools zip unzip \ + make inkscape ffmpeg flac vorbis-tools opus-tools zip \ wget \ # redis lsb-release curl gpg \ @@ -19,7 +19,7 @@ RUN apt-get update && \ # install sed coreutils build-essential \ # Other dependencies - sudo git && \ + sudo git vim && \ # Cleanup apt-get -y autoremove @@ -28,14 +28,22 @@ WORKDIR /app # Copy all changes, particularly environment variables with discord API keys COPY . . # Run first-time setup for faster restarts -RUN ./install.sh + +RUN scripts/buildCook.sh +RUN scripts/downloadCookBuilds.sh +RUN npm install -g pm2 + +RUN yarn install +RUN yarn prisma:generate +RUN yarn run build +RUN yarn run sync # Expose app port EXPOSE 3000 # Expose API port EXPOSE 5029 # Start Craig -CMD ["sh", "-c", "/app/start.sh"] +CMD ["sh", "-c", "/app/start_docker.sh"] # Usage: diff --git a/start_docker.sh b/start_docker.sh new file mode 100755 index 00000000..c602f8ef --- /dev/null +++ b/start_docker.sh @@ -0,0 +1,14 @@ +#!/bin/bash +set -x +env +yarn prisma:deploy +yarn run sync + +DOWNLOAD_DOMAIN=$(echo $API_HOMEPAGE|awk -F'://' '{print $2}') +sed -z -E -i'' "s/(dexare:.*token:\s*)('')(.*applicationID:\s*)('')(.*downloadDomain:\s*)('localhost:5029')/\ +\1'${DISCORD_BOT_TOKEN}'\3'${DISCORD_APP_ID}'\5'${DOWNLOAD_DOMAIN//\//\\/}'/" \ +"/app/apps/bot/config/default.js" + + pm2 start /app/apps/ecosystem.config.js + pm2 save + pm2 logs \ No newline at end of file