185 lines
5.6 KiB
JavaScript
185 lines
5.6 KiB
JavaScript
//setup
|
|
const readline = require('readline');
|
|
const fs = require('fs');
|
|
|
|
var 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 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', 'key');
|
|
|
|
//TODO: chat configuration
|
|
|
|
//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);
|
|
|
|
const yml = `
|
|
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}
|
|
- DB_HOSTNAME=database
|
|
- DB_DATABASE=${projectName}
|
|
- DB_USERNAME=${projectDBUser}
|
|
- DB_PASSWORD=${projectDBPass}
|
|
- DB_TIMEZONE=${databaseTimeZone}
|
|
- SESSION_SECRET=secret
|
|
- SESSION_ADMIN=adminsecret
|
|
- NEWS_URI=https://${newsWebAddress}/news
|
|
- NEWS_KEY=${newsKey}
|
|
networks:
|
|
- app-network
|
|
depends_on:
|
|
- database
|
|
- traefik
|
|
|
|
${newsName}:
|
|
image: krgamestudios/news-server:v1.0.0
|
|
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
|
|
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
|
|
RUN apt-get update
|
|
RUN apt-get install -y mariadb-client
|
|
COPY . /app
|
|
EXPOSE 3000
|
|
|
|
ENTRYPOINT ["bash", "-c"]
|
|
CMD ["mysql --host=database --user=root --password=${databaseRootPassword} < ./startup.sql && npm start"]
|
|
`;
|
|
|
|
const scriptfile = `
|
|
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}'@'%';
|
|
|
|
FLUSH PRIVILEGES;
|
|
`;
|
|
|
|
fs.writeFileSync('docker-compose.yml', yml);
|
|
fs.writeFileSync('Dockerfile', dockerfile);
|
|
fs.writeFileSync('startup.sql', scriptfile);
|
|
})()
|
|
.then(() => rl.close())
|
|
.catch(e => console.error(e))
|
|
;
|
|
|