diff --git a/.dockerignore b/.dockerignore index 1a58c56..e01f101 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,6 +1,13 @@ +# nix thing flake.nix flake.lock -docker/ - +# node thing node_modules/ + +# useless files in the docker +*.md +# docker/ + +# PLEASE NO +.env diff --git a/Justfile b/Justfile index f1a0830..24966fa 100644 --- a/Justfile +++ b/Justfile @@ -1,21 +1,43 @@ -export FASTIFY_PRETTY_LOGS := "true" -export FASTIFY_PORT := "3001" -export FASTIFY_LOG_LEVEL := "info" +@default: + just -l -auth: +# For launching the authentification api +@auth $FASTIFY_LOG_LEVEL="info" $FASTIFY_PRETTY_LOGS="true": fastify start src/api/auth/default.js - -user: +# For launching the user data api +@user $FASTIFY_LOG_LEVEL="info" $FASTIFY_PRETTY_LOGS="true": fastify start src/api/user/default.js -apis: +# To launch all apis +@apis: node src/dev.js -front: +# To launch the front end +@front: vite +# To build the front end +@build-front: + @vite build -front-build: - vite build +# To build the base of the for the fastify docker images +@build-node-base: + docker build -t node-base -f docker/api-base/Dockerfile . -front-preview: - vite preview +# To launch the docker compose +@docker: + docker compose -f docker/docker-compose.yml up -d --build + +# To stop the docker compose +@stop-docker: + docker compose -f docker/docker-compose.yml down + +# To rebuild fully the docker (use it with caution) +@re-docker: clean-docker docker + +# To completely docker +@clean-docker: clean-compose + docker system prune -af + +# To clean only the container launched by the compose +@clean-compose: stop-docker + docker compose -f docker/docker-compose.yml rm diff --git a/dev.js b/dev.js deleted file mode 100644 index a0ab584..0000000 --- a/dev.js +++ /dev/null @@ -1,32 +0,0 @@ -import Fastify from 'fastify'; -import authApi from './api/auth/default.js'; -import userApi from './api/user/default.js'; - -const loggerOption = { - transport: { - target: 'pino-pretty', - options: { - colorize: true, - translateTime: 'HH:MM:ss', - ignore: 'pid,hostname' - } - } -}; - -async function start() { - const auth = Fastify({ - logger: loggerOption - }); - auth.register(authApi); - await auth.listen({ port: 3001 }); - console.log('Auth API listening on http://localhost:3001'); - - const user = Fastify({ - logger: loggerOption - }); - user.register(userApi); - await user.listen({ port: 3002 }); - console.log('User data API listening on http://localhost:3002'); -} - -start().catch(console.error); diff --git a/docker/api-base/Dockerfile b/docker/api-base/Dockerfile new file mode 100644 index 0000000..7e4437a --- /dev/null +++ b/docker/api-base/Dockerfile @@ -0,0 +1,24 @@ +FROM node:lts-alpine AS builder + +# copy all the nessecary file to download the dependency +COPY package.json pnpm-lock.yaml pnpm-workspace.yaml /app/ + +# install all the dependency +RUN npm install -g pnpm +RUN cd /app \ + && pnpm install --prod + +FROM node:lts-alpine AS base + +# copy the source files +COPY src /app/src + +# copy the downloaded files +COPY --from=builder /app/node_modules /app/node_modules +COPY --from=builder /app/pnpm-lock.yaml /app/pnpm-lock.yaml +COPY --from=builder /app/package.json /app/package.json + +ENV NODE_ENV=production +EXPOSE 3000 + +CMD [ "node", "/app/src/start.js" ] diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml new file mode 100644 index 0000000..15819d1 --- /dev/null +++ b/docker/docker-compose.yml @@ -0,0 +1,49 @@ +services: + front: + container_name: transcendence-front + build: + dockerfile: docker/front/Dockerfile + context: .. + ports: + - 8443:443 + environment: + SERVER_NAME: localhost + depends_on: + user-api: + condition: service_started + auth-api: + condition: service_started + networks: + - front + user-api: + container_name: transcendence-api-user + build: + dockerfile: docker/api-base/Dockerfile + context: .. + tags: + - api-base + networks: + - front + - back + environment: + - API_TARGET=user + auth-api: + container_name: transcendence-api-auth + build: + dockerfile: docker/api-base/Dockerfile + context: .. + networks: + - front + - back + environment: + - API_TARGET=auth + + + +networks: + front: + external: false + name: front-backend + back: + external: false + name: trans-backend diff --git a/docker/front/Dockerfile b/docker/front/Dockerfile new file mode 100644 index 0000000..f5e1207 --- /dev/null +++ b/docker/front/Dockerfile @@ -0,0 +1,29 @@ +FROM node:lts-alpine AS builder + +RUN npm install -g pnpm + +WORKDIR /app + +COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./ + +RUN pnpm install --frozen-lockfile + +COPY vite.config.js tailwind.config.js ./ +COPY src ./src + +RUN pnpm vite build + +FROM owasp/modsecurity-crs:nginx-alpine + +RUN mkdir -p /etc/nginx/modsecurity.d \ + && cp /etc/modsecurity.d/unicode.mapping /etc/nginx/modsecurity.d/unicode.mapping + +COPY docker/front/config/default.conf.template \ + /etc/nginx/templates/conf.d/default.conf.template + +COPY --chmod=755 docker/front/entry/ssl-cert.sh /docker-entrypoint.d/ssl-cert.sh + +COPY --from=builder /app/dist /usr/share/nginx/html + +EXPOSE 80 443 +STOPSIGNAL SIGINT diff --git a/docker/front/config/default.conf.template b/docker/front/config/default.conf.template new file mode 100644 index 0000000..68b9e75 --- /dev/null +++ b/docker/front/config/default.conf.template @@ -0,0 +1,41 @@ +server { + listen 443 ssl; + server_name example.com; # Replace with your domain or handle env vars externally + + ssl_certificate /etc/nginx/certs/fullchain.pem; + ssl_certificate_key /etc/nginx/certs/privkey.pem; + + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers HIGH:!aNULL:!MD5; + + root /usr/share/nginx/html; + index index.html; + + modsecurity on; + + location / { + try_files $uri $uri/ =404; + } + + location /api/v1/user/ { + proxy_pass http://transcendence-api-user:3000/; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + location /api/v1/auth/ { + proxy_pass http://transcendence-api-auth:3000/; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } +} + +server { + listen 80; + server_name example.com; + return 301 https://$host$request_uri; +} diff --git a/docker/front/entry/ssl-cert.sh b/docker/front/entry/ssl-cert.sh new file mode 100644 index 0000000..5c2a073 --- /dev/null +++ b/docker/front/entry/ssl-cert.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +if [ ! -f /etc/nginx/certs/fullchain.pem ] || [ ! -f /etc/nginx/certs/privkey.pem ]; then + echo "Generating self-signed certs..." + mkdir -p /etc/nginx/certs + openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ + -keyout /etc/nginx/certs/privkey.pem \ + -out /etc/nginx/certs/fullchain.pem \ + -subj "/C=FR/ST=IDF/L=Angouleme/O=42/OU=42/CN=trans.kanel.ovh/UID=adjoly" +fi diff --git a/package.json b/package.json index a9dd300..839ae51 100644 --- a/package.json +++ b/package.json @@ -6,11 +6,11 @@ "bcrypt": "^6.0.0", "better-sqlite3": "^12.2.0", "fastify": "^5.4.0", - "fastify-cli": "^7.4.0", - "typescript": "^5.8.3" + "fastify-cli": "^7.4.0" }, "type": "module", "devDependencies": { + "typescript": "^5.8.3", "tailwindcss": "^4.1.11", "@tailwindcss/vite": "^4.1.11", "pino-pretty": "^13.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c1018d4..4a38815 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -29,9 +29,6 @@ importers: fastify-cli: specifier: ^7.4.0 version: 7.4.0 - typescript: - specifier: ^5.8.3 - version: 5.8.3 devDependencies: '@tailwindcss/vite': specifier: ^4.1.11 @@ -42,6 +39,9 @@ importers: tailwindcss: specifier: ^4.1.11 version: 4.1.11 + typescript: + specifier: ^5.8.3 + version: 5.8.3 vite: specifier: ^6.3.5 version: 6.3.5(jiti@2.4.2)(lightningcss@1.30.1) diff --git a/src/dev.js b/src/dev.js deleted file mode 100644 index a0ab584..0000000 --- a/src/dev.js +++ /dev/null @@ -1,32 +0,0 @@ -import Fastify from 'fastify'; -import authApi from './api/auth/default.js'; -import userApi from './api/user/default.js'; - -const loggerOption = { - transport: { - target: 'pino-pretty', - options: { - colorize: true, - translateTime: 'HH:MM:ss', - ignore: 'pid,hostname' - } - } -}; - -async function start() { - const auth = Fastify({ - logger: loggerOption - }); - auth.register(authApi); - await auth.listen({ port: 3001 }); - console.log('Auth API listening on http://localhost:3001'); - - const user = Fastify({ - logger: loggerOption - }); - user.register(userApi); - await user.listen({ port: 3002 }); - console.log('User data API listening on http://localhost:3002'); -} - -start().catch(console.error); diff --git a/src/start.js b/src/start.js new file mode 100644 index 0000000..ae048c9 --- /dev/null +++ b/src/start.js @@ -0,0 +1,46 @@ +import Fastify from 'fastify'; +import authApi from './api/auth/default.js'; +import userApi from './api/user/default.js'; + +const loggerOption = { + transport: { + target: 'pino-pretty', + options: { + colorize: true, + translateTime: 'HH:MM:ss', + ignore: 'pid,hostname' + } + } +}; + +async function start() { + const target = process.env.API_TARGET || 'all'; + + if (target === 'auth' || target === 'all') { + const auth = Fastify({ logger: loggerOption }); + auth.register(authApi); + if (target !== 'all') { + await auth.listen({ port: 3000, host: '0.0.0.0' }); + console.log('Auth API listening on http://0.0.0.0:3000'); + } + else { + await auth.listen({ port: 3001, host: '127.0.0.1'}); + console.log('Auth API listening on http://localhost:3001'); + } + } + + if (target === 'user' || target === 'all') { + const user = Fastify({ logger: loggerOption }); + user.register(userApi); + if (target !== 'all') { + await user.listen({ port: 3000, host: '0.0.0.0' }); + console.log('User API listening on http://0.0.0.0:3000'); + } + else { + await user.listen({ port: 3002, host: '127.0.0.1'}); + console.log('User API listening on http://localhost:3002'); + } + } +} + +start().catch(console.error);