diff --git a/.gitignore b/.gitignore index 8a8628d..6c02508 100644 --- a/.gitignore +++ b/.gitignore @@ -104,4 +104,8 @@ dist .tern-port # Docker generated files and folders -data/ +letsencrypt/ +mysql/ +Dockerfile +docker-compose.yml +startup.sql diff --git a/configure-script.js b/configure-script.js new file mode 100644 index 0000000..3ac564d --- /dev/null +++ b/configure-script.js @@ -0,0 +1,151 @@ +//setup +const readline = require('readline'); +const fs = require('fs'); +const crypto = require("crypto"); + +const uuid = (bytes = 16) => crypto.randomBytes(bytes).toString("hex"); + +const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout, + terminal: false +}); + +//manually promisify this (util didn't work) +const question = (prompt, def = null) => { + return new Promise((resolve, reject) => { + rl.question(`${prompt}${def ? ` (${def})` : ''}: `, answer => { + //loop on required + if (def === null && !answer) { + return resolve(question(prompt, def)); + } + + return resolve(answer || def); + }); + }); +}; + +//questions +(async () => { + //project configuration + const appName = await question('App Name', 'auth'); + const appWebAddress = await question('Web Addr', `${appName}.example.com`); + const appPort = await question('App Port', '3200'); + + const appDBUser = await question('DB User', appName); + const appDBPass = await question('DB Pass', uuid()); + const dbRootPass = await question('DB Root Pass'); + + const appMailSMTP = await question('Mail SMTP', 'smtp.example.com'); + const appMailUser = await question('Mail User', 'example@example.com'); + const appMailPass = await question('Mail Pass'); + const appMailPhysical = await question('Mail Physical'); + + const appDefaultUser = await question('App Default User', ''); + const appDefaultPass = await question('App Default Pass', ''); + + const appSecretAccess = await question('Access Token Secret', uuid(32)); + const appSecretRefresh = await question('Refresh Token Secret', uuid(32)); + + const supportEmail = await question('Support Email', appMailUser); + + //generate the files + const ymlfile = ` +version: '3' + +services: + app: + build: + context: . + ports: + - "${appPort}" + labels: + - "traefik.enable=true" + - "traefik.http.routers.${appName}router.rule=Host(\`${appWebAddress}\`)" + - "traefik.http.routers.${appName}router.entrypoints=websecure" + - "traefik.http.routers.${appName}router.tls.certresolver=myresolver" + - "traefik.http.routers.${appName}router.service=${appName}service@docker" + - "traefik.http.services.${appName}service.loadbalancer.server.port=${appPort}" + environment: + - WEB_PROTOCOL=https + - WEB_ADDRESS=${appWebAddress} + - WEB_PORT=${appPort} + - DB_HOSTNAME=database + - DB_DATABASE=${appName} + - DB_USERNAME=${appDBUser} + - DB_PASSWORD=${appDBPass} + - DB_TIMEZONE=Australia/Sydney + - MAIL_SMTP=${appMailSMTP} + - MAIL_USERNAME=${appMailUser} + - MAIL_PASSWORD=${appMailPass} + - MAIL_PHYSICAL=${appMailPhysical} + - ADMIN_DEFAULT_USERNAME=${appDefaultUser} + - ADMIN_DEFAULT_PASSWORD=${appDefaultPass} + - SECRET_ACCESS=${appSecretAccess} + - SECRET_REFRESH=${appSecretRefresh} + networks: + - app-network + depends_on: + - database + database: + image: mariadb:latest + environment: + MYSQL_DATABASE: ${appName} + MYSQL_USER: ${appDBUser} + MYSQL_PASSWORD: ${appDBPass} + MYSQL_ROOT_PASSWORD: ${dbRootPass} + networks: + - app-network + volumes: + - ./mysql:/var/lib/mysql + traefik: + image: "traefik:v2.4" + container_name: "traefik" + command: + - "--log.level=ERROR" + - "--api.insecure=false" + - "--providers.docker=true" + - "--providers.docker.exposedbydefault=false" + - "--entrypoints.websecure.address=:443" + - "--certificatesresolvers.myresolver.acme.tlschallenge=true" + - "--certificatesresolvers.myresolver.acme.email=${supportEmail}" + - "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json" + ports: + - "80:80" + - "443:443" + volumes: + - "./letsencrypt:/letsencrypt" + - "/var/run/docker.sock:/var/run/docker.sock:ro" + - "./startup.sql:/docker-entrypoint-initdb.d/startup.sql:ro" + networks: + - app-network +networks: + app-network: + driver: bridge +`; + + const dockerfile = ` +FROM node:15 +WORKDIR "/app" +COPY package*.json ./ +RUN npm install --production +COPY . /app +EXPOSE ${appPort} +USER node +ENTRYPOINT ["bash", "-c"] +CMD ["sleep 10 && npm start"] +`; + + const sqlfile = ` +CREATE DATABASE IF NOT EXISTS ${appName}; +CREATE USER IF NOT EXISTS '${appDBUser}'@'%' IDENTIFIED BY '${appDBPass}'; +GRANT ALL PRIVILEGES ON ${appName}.* TO '${appDBUser}'@'%'; +`; + + fs.writeFileSync('docker-compose.yml', ymlfile); + fs.writeFileSync('Dockerfile', dockerfile); + fs.writeFileSync('startup.sql', sqlfile); +})() + .then(() => rl.close()) + .catch(e => console.error(e)) +; diff --git a/package-lock.json b/package-lock.json index 5a429fd..8164c1a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,7 @@ "version": "1.0.0", "license": "ISC", "dependencies": { + "bcryptjs": "^2.4.3", "body-parser": "^1.19.0", "cors": "^2.8.5", "dotenv": "^8.2.0", @@ -19,7 +20,6 @@ "sequelize": "^6.5.0" }, "devDependencies": { - "bcryptjs": "^2.4.3", "nodemon": "^2.0.7" } }, @@ -187,8 +187,7 @@ "node_modules/bcryptjs": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", - "integrity": "sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms=", - "dev": true + "integrity": "sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms=" }, "node_modules/binary-extensions": { "version": "2.2.0", @@ -2298,8 +2297,7 @@ "bcryptjs": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", - "integrity": "sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms=", - "dev": true + "integrity": "sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms=" }, "binary-extensions": { "version": "2.2.0", diff --git a/package.json b/package.json index 4c30eb8..14df8cd 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ }, "homepage": "https://github.com/krgamestudios/auth-server#readme", "dependencies": { + "bcryptjs": "^2.4.3", "body-parser": "^1.19.0", "cors": "^2.8.5", "dotenv": "^8.2.0", @@ -30,7 +31,6 @@ "sequelize": "^6.5.0" }, "devDependencies": { - "bcryptjs": "^2.4.3", "nodemon": "^2.0.7" } } diff --git a/test/startup.sql b/test/debug-startup.sql similarity index 100% rename from test/startup.sql rename to test/debug-startup.sql