Files
MERN-template/configure-script.js
T
Ratstail91 b0ac371a43 Tweaking deployment startup, read more
MariaDB's root password needs to be hidden from the game server's container,
so I've changed the startup logic. MariaDB supposedly runs certain files that
are found in a specific directory, so I'm using volumes to place startup.sql
there.

This needs testing on a mock deployment server.

Related to #1
2021-03-04 06:15:46 +11:00

205 lines
6.5 KiB
JavaScript

//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) => {
return new Promise((resolve, reject) => {
rl.question(`${prompt} (${def}): `, answer => {
resolve(answer || def);
});
});
};
//questions
(async () => {
//project configuration
const projectName = await question('Project Name', 'template');
const projectWebAddress = await question('Project Web Address', 'example.com');
const projectMailSMTP = await question('Project Mail SMTP', 'smtp.example.com');
const projectMailUser = await question('Project Mail Username', 'foobar@example.com');
const projectMailPass = await question('Project Mail Password', 'foobar');
const projectMailPhysical = await question('Project Physical Mailing Address', '');
const projectDBUser = await question('Project Database Username', projectName);
const projectDBPass = await question('Project Database Password', 'pikachu');
//news configuration
const newsName = await question('News Name', 'news');
const newsWebAddress = await question('News Web Address', 'news.example.com');
const newsDBUser = await question('News Database Username', newsName);
const newsDBPass = await question('News Database Password', 'charizard');
const newsKey = await question('News Query Key', uuid());
//chat configuration
const chatName = await question('Chat Name', 'chat');
const chatWebAddress = await question('Chat Web Address', 'chat.example.com');
const chatDBUser = await question('Chat Database Username', chatName);
const chatDBPass = await question('Chat Database Password', 'blastoise');
const chatKey = await question('Chat Reservation Key', uuid());
//database configuration
const databaseRootPassword = await question('Database Root Password', 'password');
const databaseTimeZone = await question('Database Timezone', 'Australia/Sydney');
//traefic configuration
const supportEmail = await question('Support Email', projectMailUser);
//other random values
const sessionSecret = uuid(); //for session randomness
const sessionAdmin = uuid(128); //for checking if user is admin
//TODO: Implement chat-server as a docker container
const ymlfile = `
version: "3.6"
services:
${projectName}:
build: .
ports:
- "3000"
labels:
- "traefik.enable=true"
- "traefik.http.routers.${projectName}router.rule=Host(\`${projectWebAddress}\`)"
- "traefik.http.routers.${projectName}router.entrypoints=websecure"
- "traefik.http.routers.${projectName}router.tls.certresolver=myresolver"
- "traefik.http.routers.${projectName}router.service=${projectName}service@docker"
- "traefik.http.services.${projectName}service.loadbalancer.server.port=3000"
environment:
- WEB_PROTOCOL=https
- WEB_ADDRESS=${projectWebAddress}
- WEB_PORT=3000
- MAIL_SMTP=${projectMailSMTP}
- MAIL_USERNAME=${projectMailUser}
- MAIL_PASSWORD=${projectMailPass}
- MAIL_PHYSICAL=${projectMailPhysical}
- DB_HOSTNAME=database
- DB_DATABASE=${projectName}
- DB_USERNAME=${projectDBUser}
- DB_PASSWORD=${projectDBPass}
- DB_TIMEZONE=${databaseTimeZone}
- SESSION_SECRET=${sessionSecret}
- SESSION_ADMIN=${sessionAdmin}
- NEWS_URI=https://${newsWebAddress}/news
- NEWS_KEY=${newsKey}
- CHAT_URI=https://${chatWebAddress}/chat
- CHAT_KEY=${chatKey}
networks:
- app-network
depends_on:
- database
- traefik
${newsName}:
image: krgamestudios/news-server:latest
ports:
- "3100"
labels:
- "traefik.enable=true"
- "traefik.http.routers.${newsName}router.rule=Host(\`${newsWebAddress}\`)"
- "traefik.http.routers.${newsName}router.entrypoints=websecure"
- "traefik.http.routers.${newsName}router.tls.certresolver=myresolver"
- "traefik.http.routers.${newsName}router.service=newsservice@docker"
- "traefik.http.services.${newsName}service.loadbalancer.server.port=3100"
environment:
- WEB_PORT=3100
- DB_HOSTNAME=database
- DB_DATABASE=news
- DB_USERNAME=${newsDBUser}
- DB_PASSWORD=${newsDBPass}
- DB_TIMEZONE=${databaseTimeZone}
- QUERY_LIMIT=10
- QUERY_KEY=${newsKey}
networks:
- app-network
depends_on:
- database
- traefik
#chat:
# image: krgamestudios/chat-server
# ports:
# - "3200:3200"
database:
image: mariadb
restart: always
environment:
MYSQL_ROOT_PASSWORD: ${databaseRootPassword}
volumes:
- "./mysql:/var/lib/mysql"
- "./startup.sql:/docker-entrypoint-initdb.d/startup.sql:ro"
networks:
- app-network
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"
- " traefik.docker.network=app-network"
ports:
- "80:80"
- "443:443"
volumes:
- "./letsencrypt:/letsencrypt"
- "/var/run/docker.sock:/var/run/docker.sock:ro"
networks:
- app-network
networks:
app-network:
driver: bridge
`;
const dockerfile = `
FROM node:15
WORKDIR "/app"
COPY package*.json ./
RUN npm install
COPY . /app
EXPOSE 3000
ENTRYPOINT ["bash", "-c"]
CMD ["npm start"]
`;
const sqlfile = `
CREATE DATABASE IF NOT EXISTS ${projectName};
CREATE USER IF NOT EXISTS '${projectDBUser}'@'%' IDENTIFIED BY '${projectDBPass}';
GRANT ALL PRIVILEGES ON ${projectName}.* TO '${projectDBUser}'@'%';
CREATE DATABASE IF NOT EXISTS ${newsName};
CREATE USER IF NOT EXISTS '${newsDBUser}'@'%' IDENTIFIED BY '${newsDBPass}';
GRANT ALL PRIVILEGES ON ${newsName}.* TO '${newsDBUser}'@'%';
CREATE DATABASE IF NOT EXISTS ${chatName};
CREATE USER IF NOT EXISTS '${chatDBUser}'@'%' IDENTIFIED BY '${chatDBPass}';
GRANT ALL PRIVILEGES ON ${chatName}.* TO '${chatDBUser}'@'%';
FLUSH PRIVILEGES;
`;
fs.writeFileSync('docker-compose.yml', ymlfile);
fs.writeFileSync('Dockerfile', dockerfile);
fs.writeFileSync('startup.sql', sqlfile);
})()
.then(() => rl.close())
.catch(e => console.error(e))
;