Skip to content

Commit 1c7bb26

Browse files
committed
dockerized the app, better ui for teacher buttons, better working font size class
1 parent ca8292c commit 1c7bb26

File tree

14 files changed

+364
-153
lines changed

14 files changed

+364
-153
lines changed

Diff for: .env.template

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
VERSION=
2+
DOMAIN=
3+
CERTBOT_EMAIL=
4+
5+
HOST_PORT=80
6+
HOST_PORT_SSL=443
7+
API_PORT=3001
8+
API_HOST_PORT=3001

Diff for: .gitignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,5 @@ web/prod/basement_floor.jpg
3232
web/prod/first_floor.jpg
3333
web/prod/ground_floor.jpg
3434
web/prod/second_floor.jpg
35-
goptivum
35+
goptivum
36+
certbot

Diff for: api/v1/api.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"strconv"
88

99
"smuggr.xyz/goptivum/api/v1/routes"
10+
"smuggr.xyz/goptivum/api/v1/middleware"
1011
"smuggr.xyz/goptivum/common/config"
1112
"smuggr.xyz/goptivum/common/models"
1213

@@ -25,9 +26,12 @@ func Initialize(scheduleChannels *models.ScheduleChannels) chan error {
2526
gin.SetMode(os.Getenv("GIN_MODE"))
2627

2728
DefaultRouter = gin.Default()
29+
DefaultRouter.Use(middleware.NormalizeTrailingSlashMiddleware())
30+
// DefaultRouter.UseRawPath = true
31+
// DefaultRouter.RedirectTrailingSlash = false
2832

2933
DefaultRouter.Use(cors.New(cors.Config{
30-
AllowOrigins: []string{"http://localhost:3000", "http://localhost:3002", "https://zsem.smuggr.xyz"},
34+
AllowOrigins: []string{"http://localhost:3000", "http://localhost:3002", "http://localhost:3001", "https://zsem.smuggr.xyz"},
3135
AllowMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
3236
AllowHeaders: []string{"Origin", "Content-Type", "X-Auth-Token"},
3337
ExposeHeaders: []string{"Content-Length"},

Diff for: api/v1/middleware/middleware.go

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// middleware/middleware.go
2+
package middleware
3+
4+
import "github.com/gin-gonic/gin"
5+
6+
func NormalizeTrailingSlashMiddleware() gin.HandlerFunc {
7+
return func(c *gin.Context) {
8+
path := c.Request.URL.Path
9+
if len(path) > 1 && path[len(path)-1] == '/' {
10+
c.Request.URL.Path = path[:len(path)-1]
11+
}
12+
c.Next()
13+
}
14+
}

Diff for: api/v1/routes/generic.go

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ func SetupGenericRoutes(router *gin.Engine, rootGroup *gin.RouterGroup, schedule
1515
healthGroup := rootGroup.Group("/health")
1616
{
1717
healthGroup.GET("/ping", handlers.PingHandler)
18+
healthGroup.GET("", handlers.APIHealthHandler)
1819
healthGroup.GET("/", handlers.APIHealthHandler)
1920
}
2021

Diff for: api/v1/routes/schedule.go

+3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ func SetupScheduleRoutes(router *gin.Engine, rootGroup *gin.RouterGroup) {
1414
}
1515
divisionsGroup := rootGroup.Group("/divisions")
1616
{
17+
divisionsGroup.GET("", handlers.GetDivisionsHandler)
1718
divisionsGroup.GET("/", handlers.GetDivisionsHandler)
1819
}
1920

@@ -23,6 +24,7 @@ func SetupScheduleRoutes(router *gin.Engine, rootGroup *gin.RouterGroup) {
2324
}
2425
teachersGroup := rootGroup.Group("/teachers")
2526
{
27+
teachersGroup.GET("", handlers.GetTeachersHandler)
2628
teachersGroup.GET("/", handlers.GetTeachersHandler)
2729
}
2830

@@ -32,6 +34,7 @@ func SetupScheduleRoutes(router *gin.Engine, rootGroup *gin.RouterGroup) {
3234
}
3335
roomsGroup := rootGroup.Group("/rooms")
3436
{
37+
roomsGroup.GET("", handlers.GetRoomsHandler)
3538
roomsGroup.GET("/", handlers.GetRoomsHandler)
3639
}
3740
}

Diff for: docker-compose.yml

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
version: '3.8'
2+
3+
services:
4+
nginx:
5+
image: nginx:latest
6+
container_name: nginx
7+
volumes:
8+
- ./nginx/zsem.smuggr.xyz.conf:/etc/nginx/conf.d/default.conf
9+
- ./certbot/etc:/etc/letsencrypt
10+
- ./certbot/www/certbot:/var/www/certbot
11+
ports:
12+
- "${HOST_PORT:-80}:80"
13+
- "${HOST_PORT_SSL:-443}:443"
14+
environment:
15+
- SERVER_NAME=${DOMAIN}
16+
depends_on:
17+
- goptivum
18+
networks:
19+
- app-network
20+
21+
goptivum:
22+
image: smeggmann99/goptivum:${VERSION}
23+
container_name: goptivum
24+
build:
25+
context: .
26+
dockerfile: dockerfile
27+
environment:
28+
- API_PORT=${API_PORT:-3001}
29+
- DIST_PATH=/app/dist
30+
ports:
31+
- "${API_HOST_PORT:-3001}:${API_PORT:-3001}"
32+
networks:
33+
- app-network
34+
volumes:
35+
- ./build/Goptivum/dist:/app/dist
36+
- ./build/Goptivum/config.json:/app/config.json
37+
- ./build/Goptivum/.env:/app/.env
38+
39+
certbot:
40+
image: certbot/certbot
41+
container_name: certbot
42+
volumes:
43+
- certbot_etc:/etc/letsencrypt
44+
- certbot_var:/var/lib/letsencrypt
45+
- ./certbot/www/certbot:/var/www/certbot
46+
command: >
47+
certonly
48+
--webroot
49+
--webroot-path=/var/www/certbot
50+
--agree-tos
51+
--email ${CERTBOT_EMAIL:[email protected]}
52+
--no-eff-email
53+
-d ${DOMAIN}
54+
55+
certbot-renew:
56+
image: certbot/certbot
57+
container_name: certbot-renew
58+
volumes:
59+
- ./certbot/etc:/etc/letsencrypt
60+
- ./certbot/var:/var/lib/letsencrypt
61+
- ./certbot/www/certbot:/var/www/certbot
62+
entrypoint: /bin/sh -c "trap exit TERM; while :; do certbot renew --webroot -w /var/www/certbot --deploy-hook 'nginx -s reload'; sleep 12h; done"
63+
64+
networks:
65+
app-network:
66+
67+
volumes:
68+
certbot_etc:
69+
certbot_var:

Diff for: dockerfile

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
FROM golang:1.23.3 AS builder
2+
3+
RUN apt-get update && apt-get install -y \
4+
build-essential \
5+
git \
6+
make \
7+
nodejs \
8+
npm \
9+
ca-certificates
10+
11+
WORKDIR /app
12+
13+
COPY . .
14+
15+
RUN make
16+
17+
FROM debian:bookworm-slim
18+
19+
# Install CA certificates for TLS so we can make requests to external services (e.g. zsem.edu.pl)
20+
RUN apt-get update && apt-get install -y ca-certificates
21+
22+
WORKDIR /app
23+
24+
COPY --from=builder /app/build/Goptivum/dist /app/dist
25+
COPY --from=builder /app/build/Goptivum/config.json /app/config.json
26+
COPY --from=builder /app/build/Goptivum/.env /app/.env
27+
COPY --from=builder /app/build/Goptivum/Goptivum /app/Goptivum
28+
29+
RUN chmod +x /app/Goptivum
30+
31+
EXPOSE 3001
32+
33+
CMD ["./Goptivum"]

Diff for: makefile

+79-17
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,31 @@ BACKEND_SOURCE_DIR := $(PROJECT_ROOT)/app
66
FRONTEND_SOURCE_DIR := $(PROJECT_ROOT)/web/prod
77

88
BUILD_DIR := $(PROJECT_ROOT)/build
9-
CURRENT_BUILD_DIR := $(BUILD_DIR)/$(BINARY_NAME)
9+
CURRENT_BUILD_DIR := $(BUILD_DIR)/Goptivum
1010
DIST_DIR := $(CURRENT_BUILD_DIR)/dist
1111

1212
DEPLOY_HOST ?= razul-server.local
1313
DEPLOY_USER ?= goptivum
1414
DEPLOY_DIR ?= ~/$(PROJECT_NAME)
1515
DEPLOY_SERVICE_NAME ?= goptivum.service
1616

17+
VERSION := $(shell grep '^VERSION=' $(PROJECT_ROOT)/.env | cut -d '=' -f 2)
18+
ARCHS := amd64 arm
19+
OS := linux
20+
21+
DOCKER_IMAGE_NAME := $(shell echo $(PROJECT_NAME) | tr '[:upper:]' '[:lower:]'):$(VERSION)
22+
DOCKER_COMPOSE := docker-compose
23+
DOCKER_COMPOSE_FILE := $(PROJECT_ROOT)/docker-compose.yml
24+
25+
DOCKERHUB_USERNAME ?= smeggmann99
26+
1727
.PHONY: all
1828
all: build build-web-install
1929

2030
.PHONY: build
2131
build: | $(CURRENT_BUILD_DIR)
2232
@echo "Building backend..."
23-
@go build -o $(CURRENT_BUILD_DIR)/$(BINARY_NAME) $(BACKEND_SOURCE_DIR)
33+
@CGO_ENABLED=0 GOOS=$(OS) GOARCH=amd64 go build -a -installsuffix cgo -o $(CURRENT_BUILD_DIR)/$(BINARY_NAME) $(BACKEND_SOURCE_DIR)
2434
@cp -r $(BACKEND_SOURCE_DIR)/config.json $(CURRENT_BUILD_DIR)/config.json
2535
@cp -r $(BACKEND_SOURCE_DIR)/.env $(CURRENT_BUILD_DIR)/.env
2636

@@ -38,35 +48,87 @@ build-web-install: | $(CURRENT_BUILD_DIR)
3848
@mkdir -p $(DIST_DIR)
3949
@cp -r $(FRONTEND_SOURCE_DIR)/dist/* $(DIST_DIR)
4050

41-
.PHONY: run
42-
run: | $(CURRENT_BUILD_DIR)
43-
@echo "Running the application..."
44-
@cd $(CURRENT_BUILD_DIR) && ./$(BINARY_NAME)
51+
.PHONY: package
52+
package: all
53+
@echo "Packaging tarballs for version $(VERSION)..."
54+
@for arch in $(ARCHS); do \
55+
BUILD_ARCHIVE=$(BUILD_DIR)/$(PROJECT_NAME)-$(VERSION)-$(OS)-static-$$arch.tar.gz; \
56+
echo "Building for $$arch..."; \
57+
TEMP_DIR=$(BUILD_DIR)/temp_$$arch; \
58+
mkdir -p $$TEMP_DIR/Goptivum; \
59+
GOOS=$(OS) GOARCH=$$arch CGO_ENABLED=0 go build -a -installsuffix cgo -o $$TEMP_DIR/Goptivum/$(BINARY_NAME) $(BACKEND_SOURCE_DIR); \
60+
cp -r $(CURRENT_BUILD_DIR)/config.json $$TEMP_DIR/Goptivum/config.json; \
61+
cp -r $(CURRENT_BUILD_DIR)/.env $$TEMP_DIR/Goptivum/.env; \
62+
cp -r $(DIST_DIR) $$TEMP_DIR/Goptivum/dist; \
63+
echo "Creating archive $$BUILD_ARCHIVE..."; \
64+
tar -czvf $$BUILD_ARCHIVE -C $$TEMP_DIR Goptivum; \
65+
rm -rf $$TEMP_DIR; \
66+
done
67+
@echo "Packaging complete. Tarballs are in $(BUILD_DIR)"
4568

46-
.PHONY: deploy
47-
deploy: all
48-
@echo "Deploying to $(DEPLOY_HOST)..."
49-
@rsync -avz --delete $(BUILD_DIR)/$(PROJECT_NAME)/ $(DEPLOY_USER)@$(DEPLOY_HOST):$(DEPLOY_DIR)
50-
@ssh -t $(DEPLOY_USER)@$(DEPLOY_HOST) 'sudo systemctl restart $(DEPLOY_SERVICE_NAME) && sudo systemctl reload nginx'
51-
@echo "Deployment complete."
69+
.PHONY: docker-build
70+
docker-build:
71+
@echo "Building Docker images with version $(VERSION)..."
72+
@VERSION=$(VERSION) $(DOCKER_COMPOSE) -f $(DOCKER_COMPOSE_FILE) build
5273

53-
$(CURRENT_BUILD_DIR):
54-
@mkdir -p $(CURRENT_BUILD_DIR)
74+
.PHONY: docker-up
75+
docker-up:
76+
@echo "Starting Docker containers..."
77+
@$(DOCKER_COMPOSE) -f $(DOCKER_COMPOSE_FILE) up -d
78+
79+
.PHONY: docker-down
80+
docker-down:
81+
@echo "Stopping Docker containers..."
82+
@$(DOCKER_COMPOSE) -f $(DOCKER_COMPOSE_FILE) down
83+
84+
.PHONY: docker-clean
85+
docker-clean:
86+
@echo "Removing Docker containers, images, and volumes..."
87+
@$(DOCKER_COMPOSE) -f $(DOCKER_COMPOSE_FILE) down --rmi all --volumes --remove-orphans
88+
89+
.PHONY: docker-publish
90+
docker-publish: docker-build
91+
@echo "Tagging Docker image for publishing..."
92+
@docker tag goptivum:$(VERSION) $(DOCKERHUB_USERNAME)/goptivum:$(VERSION)
93+
@docker tag goptivum:$(VERSION) $(DOCKERHUB_USERNAME)/goptivum:latest
94+
@echo "Pushing Docker image to Docker Hub..."
95+
@docker push $(DOCKERHUB_USERNAME)/goptivum:$(VERSION)
96+
@docker push $(DOCKERHUB_USERNAME)/goptivum:latest
5597

5698
.PHONY: clean
5799
clean:
58-
@echo "Cleaning up..."
100+
@echo "Cleaning up build files..."
59101
@rm -rf $(BUILD_DIR)
60102

103+
.PHONY: clean-tarballs
104+
clean-tarballs:
105+
@echo "Cleaning up tarballs..."
106+
@find $(BUILD_DIR) -type f -name '*.tar.gz' -delete
107+
108+
.PHONY: deploy
109+
deploy: all
110+
@echo "Deploying to $(DEPLOY_HOST)..."
111+
@rsync -avz --delete $(BUILD_DIR)/ $(DEPLOY_USER)@$(DEPLOY_HOST):$(DEPLOY_DIR)
112+
@ssh -t $(DEPLOY_USER)@$(DEPLOY_HOST) 'sudo systemctl restart $(DEPLOY_SERVICE_NAME) && sudo systemctl reload nginx'
113+
@echo "Deployment complete."
114+
61115
.PHONY: help
62116
help:
63117
@echo "Usage:"
64118
@echo " make Build the Go backend and Vue.js frontend and install NPM dependencies"
65119
@echo " make build Build the Go backend"
66120
@echo " make build-web Build the Vue.js frontend without installing NPM dependencies"
67121
@echo " make build-web-install Build the Vue.js frontend and install NPM dependencies"
68-
@echo " make run Run the application"
122+
@echo " make package Build and package the application for all architectures"
123+
@echo " make docker-build Build Docker images"
124+
@echo " make docker-up Start Docker containers"
125+
@echo " make docker-down Stop Docker containers"
126+
@echo " make docker-clean Clean up Docker containers, images, and volumes"
127+
@echo " make docker-publish Build and publish Docker images to Docker Hub"
69128
@echo " make deploy Deploy the application to the remote server"
70-
@echo " Override deploy credentials with DEPLOY_HOST, DEPLOY_USER, DEPLOY_DIR and DEPLOY_SERVICE_NAME"
71129
@echo " make clean Clean up build files"
130+
@echo " make clean-tarballs Clean up tarball archives"
72131
@echo " make help Show this help message"
132+
133+
$(CURRENT_BUILD_DIR):
134+
@mkdir -p $(CURRENT_BUILD_DIR)

Diff for: nginx/zsem.smuggr.xyz.conf

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
server {
2+
listen 80;
3+
server_name zsem.smuggr.xyz;
4+
5+
location /.well-known/acme-challenge/ {
6+
root /var/www/certbot;
7+
allow all;
8+
}
9+
10+
location / {
11+
return 301 https://$host$request_uri;
12+
}
13+
}
14+
15+
server {
16+
listen 443 ssl;
17+
server_name zsem.smuggr.xyz;
18+
19+
ssl_certificate /etc/letsencrypt/live/zsem.smuggr.xyz/fullchain.pem;
20+
ssl_certificate_key /etc/letsencrypt/live/zsem.smuggr.xyz/privkey.pem;
21+
include /etc/letsencrypt/options-ssl-nginx.conf;
22+
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
23+
24+
location / {
25+
proxy_pass http://goptivum:3001;
26+
proxy_set_header Host $host;
27+
proxy_set_header X-Real-IP $remote_addr;
28+
proxy_http_version 1.1;
29+
proxy_set_header Connection "";
30+
chunked_transfer_encoding off;
31+
proxy_buffering off;
32+
proxy_cache off;
33+
proxy_read_timeout 3600s;
34+
# add_header Cache-Control "no-store";
35+
}
36+
37+
location /.well-known/acme-challenge/ {
38+
root /var/www/certbot;
39+
allow all;
40+
}
41+
}

0 commit comments

Comments
 (0)