fix: Voorbereiding production

This commit is contained in:
Tibo De Peuter 2025-03-13 14:27:12 +01:00
parent 6a6eed8978
commit fc5ba93ba0
Signed by: tdpeuter
GPG key ID: 38297DE43F75FFE2
13 changed files with 293 additions and 257 deletions

View file

@ -1,10 +1,16 @@
DWENGO_PORT=3000
#
# Basic configuration
#
DWENGO_PORT=3000 # The port the backend will listen on
DWENGO_DB_HOST=localhost
DWENGO_DB_PORT=5431
DWENGO_DB_PORT=5432
DWENGO_DB_USERNAME=postgres
DWENGO_DB_PASSWORD=postgres
DWENGO_DB_UPDATE=true
# Auth
DWENGO_AUTH_STUDENT_URL=http://localhost:7080/realms/student
DWENGO_AUTH_STUDENT_CLIENT_ID=dwengo
DWENGO_AUTH_STUDENT_JWKS_ENDPOINT=http://localhost:7080/realms/student/protocol/openid-connect/certs
@ -14,3 +20,9 @@ DWENGO_AUTH_TEACHER_JWKS_ENDPOINT=http://localhost:7080/realms/teacher/protocol/
# Allow Vite dev-server to access the backend (for testing purposes). Don't forget to remove this in production!
DWENGO_CORS_ALLOWED_ORIGINS=http://localhost:5173
#
# Advanced configuration
#
# LOKI_HOST=http://localhost:9001 # The address of the Loki instance, used for logging

View file

@ -1,4 +1,4 @@
DWENGO_PORT=3000 # The port the backend will listen on
DWENGO_PORT=3000 # The port the backend will listen on
DWENGO_DB_HOST=domain-or-ip-of-database
DWENGO_DB_PORT=5432

View file

@ -1,7 +0,0 @@
DWENGO_PORT=3000
DWENGO_DB_HOST=localhost
DWENGO_DB_PORT=5432
DWENGO_DB_NAME=postgres
DWENGO_DB_USERNAME=postgres
DWENGO_DB_PASSWORD=postgres
DWENGO_DB_UPDATE=true

View file

@ -0,0 +1,28 @@
DWENGO_PORT=3000 # The port the backend will listen on
DWENGO_DB_HOST=db # Name of the database container
DWENGO_DB_PORT=5432
# Change this to the actual credentials of the user Dwengo should use in the backend
DWENGO_DB_NAME=postgres
DWENGO_DB_USERNAME=postgres
DWENGO_DB_PASSWORD=postgres
# Set this to true when the database scheme needs to be updated. In that case, take a backup first.
DWENGO_DB_UPDATE=false
# Data for the identity provider via which the students authenticate.
DWENGO_AUTH_STUDENT_URL=https://sel2-1.ugent.be/idp/realms/student
DWENGO_AUTH_STUDENT_CLIENT_ID=dwengo
DWENGO_AUTH_STUDENT_JWKS_ENDPOINT=http://idp:7080/idp/realms/student/protocol/openid-connect/certs # Name of the idp container
# Data for the identity provider via which the teachers authenticate.
DWENGO_AUTH_TEACHER_URL=https://sel2-1.ugent.be/idp/realms/teacher
DWENGO_AUTH_TEACHER_CLIENT_ID=dwengo
DWENGO_AUTH_TEACHER_JWKS_ENDPOINT=http://idp:7080/idp/realms/teacher/protocol/openid-connect/certs # Name of the idp container
#
# Advanced configuration
#
# Logging and monitoring
# LOKI_HOST=http://logging:3102 # The address of the Loki instance, used for logging

View file

@ -30,29 +30,29 @@ app.use(responseTime(responseTimeLogger));
app.use(authenticateUser);
// TODO Replace with Express routes
app.get('/', (_, res: Response) => {
logger.debug('GET /');
app.get('/api/', (_, res: Response) => {
logger.debug('GET /api/');
res.json({
message: 'Hello Dwengo!🚀',
});
});
app.use('/student', studentRouter);
app.use('/group', groupRouter);
app.use('/assignment', assignmentRouter);
app.use('/submission', submissionRouter);
app.use('/class', classRouter);
app.use('/question', questionRouter);
app.use('/auth', authRouter);
app.use('/theme', themeRoutes);
app.use('/learningPath', learningPathRoutes);
app.use('/learningObject', learningObjectRoutes);
app.use('/api/student', studentRouter);
app.use('/api/group', groupRouter);
app.use('/api/assignment', assignmentRouter);
app.use('/api/submission', submissionRouter);
app.use('/api/class', classRouter);
app.use('/api/question', questionRouter);
app.use('/api/auth', authRouter);
app.use('/api/theme', themeRoutes);
app.use('/api/learningPath', learningPathRoutes);
app.use('/api/learningObject', learningObjectRoutes);
async function startServer() {
await initORM();
app.listen(port, () => {
logger.info(`Server is running at http://localhost:${port}`);
logger.info(`Server is running at http://localhost:${port}/api`);
});
}

72
compose.override.yml Normal file
View file

@ -0,0 +1,72 @@
#
# Use this configuration to test the production configuration locally.
#
# This configuration builds the frontend and backend services as Docker images,
# and uses the paths for the services, instead of ports.
#
services:
web:
build:
context: .
dockerfile: frontend/Dockerfile
ports:
- '8080:8080/tcp'
restart: unless-stopped
labels:
- 'traefik.http.routers.web.rule=PathPrefix(`/`)'
- 'traefik.http.services.web.loadbalancer.server.port=8080'
api:
build:
context: .
dockerfile: backend/Dockerfile
ports:
- '3000:3000/tcp'
restart: unless-stopped
volumes:
- ./backend/.env:/app/.env
depends_on:
- db
- logging
labels:
- 'traefik.http.routers.api.rule=PathPrefix(`/api`)'
- 'traefik.http.services.api.loadbalancer.server.port=3000'
idp:
# Also see compose.yml
labels:
- 'traefik.http.routers.idp.rule=PathPrefix(`/idp`)'
- 'traefik.http.services.idp.loadbalancer.server.port=7080'
environment:
PROXY_ADDRESS_FORWARDING: 'true'
KC_HTTP_RELATIVE_PATH: '/idp'
reverse-proxy:
image: traefik:v3.3
command:
# Enable web UI
- '--api.insecure=true'
# Add Docker provider
- '--providers.docker=true'
- '--providers.docker.exposedbydefault=true'
# Add web entrypoint
- '--entrypoints.web.address=:80/tcp'
ports:
- '9000:8080'
- '80:80/tcp'
restart: unless-stopped
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
dashboards:
image: grafana/grafana:latest
ports:
- '9002:3000'
volumes:
- dwengo_grafana_data:/var/lib/grafana
restart: unless-stopped
volumes:
dwengo_grafana_data:

110
compose.prod.yml Normal file
View file

@ -0,0 +1,110 @@
#
# This file is used to define the production environment for the project.
# It is used to deploy the project on a server.
# Should not be used for local development.
#
services:
web:
build:
context: .
dockerfile: frontend/Dockerfile
restart: unless-stopped
networks:
- dwengo-1
labels:
- 'traefik.enable=true'
- 'traefik.http.routers.web.rule=PathPrefix(`/`)'
- 'traefik.http.services.web.loadbalancer.server.port=80'
api:
build:
context: .
dockerfile: backend/Dockerfile
restart: unless-stopped
volumes:
# TODO Replace with environment keys
- ./backend/.env:/app/.env
depends_on:
- db
- logging
networks:
- dwengo-1
labels:
- 'traefik.enable=true'
- 'traefik.http.routers.api.rule=PathPrefix(`/api`)'
- 'traefik.http.services.api.loadbalancer.server.port=3000'
db:
# Also see compose.yml
networks:
- dwengo-1
idp:
# Also see compose.yml
# TODO Replace with proper production command
command: ['start-dev', '--http-port', '7080', '--https-port', '7443', '--import-realm']
networks:
- dwengo-1
labels:
- 'traefik.enable=true'
- 'traefik.http.routers.idp.rule=PathPrefix(`/idp`)'
- 'traefik.http.services.idp.loadbalancer.server.port=7080'
env_file:
- ./config/idp/.env
environment:
KC_HOSTNAME: 'sel2-1.ugent.be'
PROXY_ADDRESS_FORWARDING: 'true'
KC_HTTP_RELATIVE_PATH: '/idp'
reverse-proxy:
image: traefik:v3.3
ports:
- '80:80/tcp'
- '443:443/tcp'
command:
# Add Docker provider
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
# Add web entrypoint
- "--entrypoints.web.address=:80/tcp"
- "--entrypoints.web.http.redirections.entryPoint.to=websecure"
- "--entrypoints.web.http.redirections.entryPoint.scheme=https"
# Add websecure entrypoint
- "--entrypoints.websecure.address=:443/tcp"
- "--entrypoints.websecure.http.tls=true"
- "--entrypoints.websecure.http.tls.certResolver=letsencrypt"
- "--entrypoints.websecure.http.tls.domains[0].main=sel2-1.ugent.be"
# Certificates
- "--certificatesresolvers.letsencrypt.acme.httpchallenge=true"
- "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
- "--certificatesresolvers.letsencrypt.acme.email=timo.demeyst@ugent.be"
- "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
restart: unless-stopped
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- dwengo_letsencrypt:/letsencrypt
networks:
- dwengo-1
logging:
# Also see compose.yml
networks:
- dwengo-1
dashboards:
image: grafana/grafana:latest
ports:
- '9002:3000'
restart: unless-stopped
volumes:
- dwengo_grafana_data:/var/lib/grafana
volumes:
dwengo_grafana_data:
dwengo_letsencrypt:
networks:
dwengo-1:

52
compose.yml Normal file
View file

@ -0,0 +1,52 @@
#
# Use this configuration during development.
#
# This configuration is suitable to access the services using their ports.
#
services:
db:
image: postgres:latest
ports:
- '5432:5432'
restart: unless-stopped
volumes:
- dwengo_postgres_data:/var/lib/postgresql/data
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: postgres
idp: # Based on: https://medium.com/@fingervinicius/easy-running-keycloak-with-docker-compose-b0d7a4ee2358
image: quay.io/keycloak/keycloak:latest
ports:
- '7080:7080'
# - '7443:7443'
command: [ 'start-dev', '--http-port', '7080', '--https-port', '7443', '--import-realm' ]
restart: unless-stopped
volumes:
- ./config/idp:/opt/keycloak/data/import
depends_on:
- db
environment:
KC_HOSTNAME: localhost
KC_HOSTNAME_PORT: 7080
KC_HOSTNAME_STRICT_BACKCHANNEL: 'true'
KC_BOOTSTRAP_ADMIN_USERNAME: admin
KC_BOOTSTRAP_ADMIN_PASSWORD: admin
KC_HEALTH_ENABLED: 'true'
KC_LOG_LEVEL: info
logging:
image: grafana/loki:latest
ports:
- '9001:3102'
- '9095:9095'
command: -config.file=/etc/loki/config.yaml
restart: unless-stopped
volumes:
- ./config/loki/config.yml:/etc/loki/config.yaml
- dwengo_loki_data:/loki
volumes:
dwengo_loki_data:
dwengo_postgres_data:

View file

@ -15,7 +15,7 @@ http {
}
server {
listen 80;
listen 8080;
location / {
root /usr/share/nginx/html;

View file

@ -1,111 +0,0 @@
services:
web:
build:
context: .
dockerfile: ./frontend/Dockerfile
restart: unless-stopped
networks:
- dwengo-1
labels:
- 'traefik.enable=true'
- 'traefik.http.routers.web.rule=PathPrefix(`/`)'
- 'traefik.http.services.web.loadbalancer.server.port=80'
api:
build:
context: .
dockerfile: ./backend/Dockerfile
restart: unless-stopped
volumes:
# TODO Replace with environment keys
- ./backend/.env:/app/.env
networks:
- dwengo-1
depends_on:
- db
- logging
labels:
- 'traefik.enable=true'
- 'traefik.http.middlewares.api-prefix.stripprefix.prefixes=/api'
- 'traefik.http.routers.api.rule=Host(`sel2-1.ugent.be`)'
- 'traefik.http.routers.api.rule=PathPrefix(`/api`)'
- 'traefik.http.routers.api.middlewares=api-prefix'
- 'traefik.http.services.api.loadbalancer.server.port=3000'
db:
image: postgres:latest
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: postgres
restart: unless-stopped
volumes:
- dwengo_postgres_data:/var/lib/postgresql/data
networks:
- dwengo-1
reverse-proxy:
image: traefik:v3.3
command: >
--api.insecure=true
--providers.docker=true
--providers.docker.exposedbydefault=false
--entrypoints.web.address=:80/tcp
--entrypoints.web.http.redirections.entryPoint.to=websecure
--entrypoints.web.http.redirections.entrypoint.scheme=https
--entrypoints.websecure.address=:443/tcp
--entrypoints.websecure.http.tls=true
--entrypoints.websecure.http.tls.certResolver=letsencrypt
--entrypoints.websecure.http.tls.domains[0].main=sel2-1.ugent.be
--certificatesresolvers.letsencrypt.acme.email=timo.demeyst@ugent.be
--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json
--certificatesresolvers.letsencrypt.acme.httpChallenge=true
--certificatesresolvers.letsencrypt.acme.httpChallenge.entrypoint=web
ports:
- '8080:8080'
- '80:80/tcp'
- '443:443/tcp'
restart: unless-stopped
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- dwengo_letsencrypt:/letsencrypt:ro
networks:
- dwengo-1
logging:
image: grafana/loki:latest
ports:
- '3102:3102'
- '9095:9095'
volumes:
- ./config/loki/config.yml:/etc/loki/config.yaml
- dwengo_loki_data:/loki
command: -config.file=/etc/loki/config.yaml
restart: unless-stopped
networks:
- dwengo-1
labels:
- 'traefik.enable=true'
- 'traefik.http.middlewares.logging-prefix.stripprefix.prefixes=/logging'
- 'traefik.http.routers.web.rule=PathPrefix(`/logging`)'
- 'traefik.http.routers.web.middlewares=logging-prefix'
- 'traefik.http.services.web.loadbalancer.server.port=3102'
dashboards:
image: grafana/grafana:latest
ports:
- '3100:3000'
volumes:
- dwengo_grafana_data:/var/lib/grafana
restart: unless-stopped
networks:
- dwengo-1
volumes:
dwengo_postgres_data:
dwengo_letsencrypt:
dwengo_loki_data:
dwengo_grafana_data:
networks:
dwengo-1:

View file

@ -1,120 +0,0 @@
services:
web:
build:
context: .
dockerfile: ./frontend/Dockerfile
ports:
- '8090:80/tcp'
restart: unless-stopped
# networks:
# - dwengo-1
labels:
- 'traefik.enable=true'
- 'traefik.http.routers.web.rule=PathPrefix(`/`)'
- 'traefik.http.services.web.loadbalancer.server.port=80'
api:
build:
context: .
dockerfile: ./backend/Dockerfile
ports:
- '3000:3000/tcp'
restart: unless-stopped
volumes:
- ./backend/.env:/app/.env
# networks:
# - dwengo-1
depends_on:
- db
- logging
labels:
- 'traefik.enable=true'
- 'traefik.http.middlewares.api-prefix.stripprefix.prefixes=/api'
- 'traefik.http.routers.api.rule=PathPrefix(`/api`)'
- 'traefik.http.routers.api.middlewares=api-prefix'
- 'traefik.http.services.api.loadbalancer.server.port=3000'
db:
image: postgres:latest
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: postgres
ports:
- '5431:5432'
restart: unless-stopped
volumes:
- dwengo_postgres_data:/var/lib/postgresql/data
# networks:
# - dwengo-1
reverse-proxy:
image: traefik:v3.3
command: >
--api.insecure=true
--providers.docker=true
--providers.docker.exposedbydefault=false
--entrypoints.web.address=:80/tcp
ports:
- '8080:8080'
- '80:80/tcp'
# - '443:443/tcp'
restart: unless-stopped
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- dwengo_letsencrypt:/letsencrypt:ro
# networks:
# - dwengo-1
logging:
image: grafana/loki:latest
ports:
- '3102:3102'
- '9095:9095'
volumes:
- ./config/loki/config.yml:/etc/loki/config.yaml
- dwengo_loki_data:/loki
command: -config.file=/etc/loki/config.yaml
restart: unless-stopped
# networks:
# - dwengo-1
dashboards:
image: grafana/grafana:latest
ports:
- '3100:3000'
volumes:
- dwengo_grafana_data:/var/lib/grafana
restart: unless-stopped
# networks:
# - dwengo-1
idp: # Based on: https://medium.com/@fingervinicius/easy-running-keycloak-with-docker-compose-b0d7a4ee2358
image: quay.io/keycloak/keycloak:latest
volumes:
- ./idp:/opt/keycloak/data/import
environment:
KC_HOSTNAME: localhost
KC_HOSTNAME_PORT: 7080
KC_HOSTNAME_STRICT_BACKCHANNEL: 'true'
KC_BOOTSTRAP_ADMIN_USERNAME: admin
KC_BOOTSTRAP_ADMIN_PASSWORD: admin
KC_HEALTH_ENABLED: 'true'
KC_LOG_LEVEL: info
healthcheck:
test: ['CMD', 'curl', '-f', 'http://localhost:7080/health/ready']
interval: 15s
timeout: 2s
retries: 15
command: ['start-dev', '--http-port', '7080', '--https-port', '7443', '--import-realm']
ports:
- '7080:7080'
- '7443:7443'
depends_on:
- db
volumes:
dwengo_postgres_data:
dwengo_letsencrypt:
dwengo_loki_data:
dwengo_grafana_data:

View file

@ -31,6 +31,6 @@ COPY config/nginx/nginx.conf /etc/nginx/nginx.conf
COPY --from=build-stage /app/assets /usr/share/nginx/html/assets
COPY --from=build-stage /app/frontend/dist /usr/share/nginx/html
EXPOSE 80
EXPOSE 8080
CMD ["nginx", "-g", "daemon off;"]

View file

@ -1,5 +1,5 @@
export const apiConfig = {
baseUrl: window.location.hostname == "localhost" ? "http://localhost:3000" : window.location.origin,
baseUrl: (window.location.hostname === "localhost" && !(window.location.port === '80' || window.location.port === '')) ? "http://localhost:3000/api" : window.location.origin + "/api",
};
export const loginRoute = "/login";