Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

zess: deployment #46

Merged
merged 10 commits into from
Aug 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: Docker Build and Push

on:
push:
branches:
- main
pull_request:

jobs:
build-and-push:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log in to Docker Hub
if: github.event_name == 'push'
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build Docker image
run: |
docker build . -t ghcr.io/zeuswpi/zess:pr-${{ github.sha }}
if [ "${{ github.event_name }}" == "push" ]; then
docker tag ghcr.io/zeuswpi/zess:pr-${{ github.sha }} ghcr.io/zeuswpi/zess:latest
fi

- name: Push Docker image
if: github.event_name == 'push'
run: docker push --all-tags ghcr.io/zeuswpi/zess
57 changes: 57 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Build backend
FROM golang:1.22.1-alpine3.19 as build_backend

RUN apk add upx alpine-sdk

WORKDIR /

COPY vingo/go.sum go.sum

COPY vingo/go.mod go.mod

RUN go mod download

COPY vingo/main.go .

COPY vingo/database database

COPY vingo/handlers handlers

RUN CGO_ENABLED=1 go build -ldflags "-s -w" -v -tags musl vingo/.

RUN upx --best --lzma vingo



# Build frontend
FROM node:20.15.1-alpine3.20 as build_frontend

WORKDIR /

COPY vinvoor/package.json package.json

COPY vinvoor/yarn.lock yarn.lock

RUN yarn install

COPY vinvoor/ .

COPY vinvoor/production.env .env

RUN yarn run build



# End container
FROM alpine:3.19

WORKDIR /

COPY --from=build_backend vingo .
COPY --from=build_frontend /dist public

ENV DEVELOPMENT=false

EXPOSE 4000

ENTRYPOINT ["./vingo"]
12 changes: 8 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@ Automatically run them by running `git config --local core.hooksPath .githooks/`

### Run

#### Easy & Quick

- Install Docker and Docker Compose
- Run the script `./dev.sh` with optional flags:
- `-b`: Show the output of the backend.
Expand All @@ -50,6 +48,12 @@ Automatically run them by running `git config --local core.hooksPath .githooks/`
The backend is accessible at `localhost:3000`, and the frontend at `localhost:5173`.
Both the backend and the frontend support hot module reloading (HMR).

#### Manual
## Production

- Install Docker
- Set the required env variables for vinvoor in `vinvoor/production.env` _before_ building (see the [README in ./vinvoor](vinvoor/README.md))
- Build the image `docker build -t zess .`
- Set the required variables in a `.env` file for the backend (see the [README in ./vingo](vingo/README.md))
- Run the image `docker run -v ${PWD}/.env:/.env zess`

- Each part has it's own `README.md` with instructions on how to run it.
The website is accessible on port 4000
12 changes: 6 additions & 6 deletions dev.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ done
if [ "$clean" = true ]; then
rm vingo/.env || true
rm vinvoor/.env || true
docker-compose -f docker-compose.yml build
docker compose -f docker-compose.yml build
Topvennie marked this conversation as resolved.
Show resolved Hide resolved
fi


Expand All @@ -37,19 +37,19 @@ if [ ! -f vinvoor/.env ]; then
fi

# Start the docker containers
docker-compose -f docker-compose.yml up -d
docker compose -f docker-compose.yml up -d

echo "-------------------------------------"
echo "Following logs..."
echo "Press CTRL + C to stop all containers"
echo "-------------------------------------"

if [ "$backend" = true ] && [ "$frontend" = false ]; then
docker-compose -f docker-compose.yml logs -f zess-backend
docker compose -f docker-compose.yml logs -f zess-backend
elif [ "$backend" = false ] && [ "$frontend" = true ]; then
docker-compose -f docker-compose.yml logs -f zess-frontend
docker compose -f docker-compose.yml logs -f zess-frontend
else
docker-compose -f docker-compose.yml logs -f zess-backend zess-frontend
docker compose -f docker-compose.yml logs -f zess-backend zess-frontend
fi

docker-compose -f docker-compose.yml down
docker compose -f docker-compose.yml down
29 changes: 0 additions & 29 deletions vingo/Dockerfile

This file was deleted.

15 changes: 9 additions & 6 deletions vingo/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,13 @@ Register a scan by posting `card_serial;scan_key` to the `/scans` endpoint.

To register a card, click the "Start registering a new card" button in the cards view, after which the server will register the next scanned card for the user that initiated the request. Only 1 user can register a card at a time.

## How to run (for development)
## Environment variables

- install go
- install docker
- `docker run --name zess-postgres -e POSTGRES_PASSWORD=zess -d -p 5432:5432 postgres`
- `go run .` with the appropriate env vars set (see dev.env)
- profit
- CORS_ALLOW_ORIGINS (string) | Allowed CORS
- DEVELOPMENT (bool) | Whether the program is run in development mode
- ZAUTH_URL (string) | URL of zauth
- ZAUTH_CALLBACK_PATH (string) | Callback path after the zauth authentication (should go to the backend)
- ZAUTH_CLIENT_ID (string) | ID of the zauth client
- ZAUTH_CLIENT_SECRET (string) | Secret of the zauth client
- ZAUTH_REDIRECT_URI (string) | Redirect URI after the zauth authentication is complete in the backend (should go to the frontend)
- POSTGRES_CONNECTION_STRING (string) | Connection string for the database
3 changes: 3 additions & 0 deletions vingo/dev.env
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
CORS_ALLOW_ORIGINS="http://localhost:5173"
DEVELOPMENT=true

ZAUTH_URL="https://zauth.zeus.gent"
ZAUTH_CALLBACK_PATH="/api/auth/callback"
ZAUTH_CLIENT_ID="tomtest"
ZAUTH_CLIENT_SECRET="blargh"
ZAUTH_REDIRECT_URI="http://localhost:5173"
Expand Down
21 changes: 10 additions & 11 deletions vingo/handlers/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,17 @@ import (
"github.com/gofiber/fiber/v2"
)

const (
ZAUTH_URL = "https://zauth.zeus.gent"
CALLBACK_PATH = "/auth/callback" // TODO: hardcode ono
)

var (
ZauthURL = ""
ZauthCallbackPath = ""
ZauthClientId = ""
ZauthClientSecret = ""
ZauthRedirectUri = ""
)

func SetZauth(client_id string, client_secret string, redirect_uri string) {
func SetZauth(url string, callback_path string, client_id string, client_secret string, redirect_uri string) {
ZauthURL = url
ZauthCallbackPath = callback_path
ZauthClientId = client_id
ZauthClientSecret = client_secret
ZauthRedirectUri = redirect_uri
Expand All @@ -37,8 +36,8 @@ func Login(c *fiber.Ctx) error {
sess.Set(ZAUTH_STATE, state.String())
sess.Save()

callback_url := c.BaseURL() + CALLBACK_PATH
return c.Status(200).Redirect(fmt.Sprintf("%s/oauth/authorize?client_id=%s&response_type=code&state=%s&redirect_uri=%s", ZAUTH_URL, ZauthClientId, state.String(), callback_url))
callback_url := c.BaseURL() + ZauthCallbackPath
return c.Status(200).Redirect(fmt.Sprintf("%s/oauth/authorize?client_id=%s&response_type=code&state=%s&redirect_uri=%s", ZauthURL, ZauthClientId, state.String(), callback_url))
}

func Logout(c *fiber.Ctx) error {
Expand Down Expand Up @@ -87,12 +86,12 @@ func Callback(c *fiber.Ctx) error {
defer fiber.ReleaseArgs(args)
args.Set("grant_type", "authorization_code")
args.Set("code", code)
args.Set("redirect_uri", c.BaseURL()+CALLBACK_PATH)
args.Set("redirect_uri", c.BaseURL()+ZauthCallbackPath)

// Convert callback code into access token
zauth_token := new(ZauthToken)
status, _, errs := fiber.
Post(ZAUTH_URL+"/oauth/token").
Post(ZauthURL+"/oauth/token").
BasicAuth(ZauthClientId, ZauthClientSecret).
Form(args).
Struct(zauth_token)
Expand All @@ -107,7 +106,7 @@ func Callback(c *fiber.Ctx) error {
// Get user info using access token
zauth_user := new(ZauthUser)
status, _, errs = fiber.
Get(ZAUTH_URL+"/current_user").
Get(ZauthURL+"/current_user").
Set("Authorization", "Bearer "+zauth_token.AccessToken).
Struct(zauth_user)

Expand Down
58 changes: 48 additions & 10 deletions vingo/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package main
import (
"encoding/gob"
"os"
"strconv"
"vingo/database"
"vingo/handlers"

Expand All @@ -14,7 +15,10 @@ import (
_ "github.com/lib/pq"
)

var corsAllowOrigins = ""
var (
corsAllowOrigins string
development bool
)

func main() {
gob.Register(database.User{})
Expand All @@ -25,23 +29,30 @@ func main() {
db := database.Get()
defer db.Close()

api := fiber.New(fiber.Config{})
app := fiber.New(fiber.Config{})

if development {
app.Use(cors.New(cors.Config{
AllowOrigins: corsAllowOrigins,
AllowHeaders: "Origin, Content-Type, Accept, Access-Control-Allow-Origin",
AllowCredentials: true,
}))
} else {
app.Static("/", "./public")
}

api.Use(cors.New(cors.Config{
AllowOrigins: corsAllowOrigins,
AllowHeaders: "Origin, Content-Type, Accept, Access-Control-Allow-Origin",
AllowCredentials: true,
}))
api := app.Group("/api")

// Public routes
{
// Public routes
api.Post("/login", handlers.Login)
api.Get("/auth/callback", handlers.Callback)

api.Post("/scans", handlers.ScanRegister)

api.Get("/recent_scans", handlers.PublicRecentScans)

// Protected routes
authed := api.Group("", handlers.IsLoggedIn)
{
authed.Post("/logout", handlers.Logout)
Expand All @@ -57,6 +68,7 @@ func main() {
authed.Get("/settings", handlers.Settings{}.Get)
authed.Patch("/settings", handlers.Settings{}.Update)

// Admin routes
admin := authed.Group("/admin", handlers.IsAdmin)
{
admin.Get("/days", handlers.Days{}.All)
Expand All @@ -66,7 +78,12 @@ func main() {
}
}

log.Println(api.Listen(":4000"))
// Catch-all route leading to the frontend
app.Get("*", func(c *fiber.Ctx) error {
return c.SendFile("./public/index.html")
})

log.Println(app.Listen(":4000"))
}

func setupFromEnv() {
Expand All @@ -81,7 +98,28 @@ func setupFromEnv() {
}
corsAllowOrigins = cors_allow_origins

dev, dev_ok := os.LookupEnv("DEVELOPMENT")
if !dev_ok {
log.Fatal("DEVELOPMENT environment variable not set")
}
dev_value, dev_value_err := strconv.ParseBool(dev)
if dev_value_err != nil {
log.Fatal("DEVELOPMENT environment variable is not a valid boolean")
}
development = dev_value

// stuff for Zauth oauth flow

zauth_url, url_ok := os.LookupEnv("ZAUTH_URL")
if !url_ok {
log.Fatal("ZAUTH_URL environment variable not set")
}

zauth_callback_path, callback_ok := os.LookupEnv("ZAUTH_CALLBACK_PATH")
if !callback_ok {
log.Fatal("ZAUTH_CALLBACK_PATH environment variable not set")
}

Topvennie marked this conversation as resolved.
Show resolved Hide resolved
zauth_client_id, id_ok := os.LookupEnv("ZAUTH_CLIENT_ID")
if !id_ok {
log.Fatal("ZAUTH_CLIENT_ID environment variable not set")
Expand All @@ -97,7 +135,7 @@ func setupFromEnv() {
log.Fatal("ZAUTH_REDIRECT_URI environment variable not set")
}

handlers.SetZauth(zauth_client_id, zauth_client_secret, zauth_redirect_uri)
handlers.SetZauth(zauth_url, zauth_callback_path, zauth_client_id, zauth_client_secret, zauth_redirect_uri)

// PSK that will authorize the scanner
scan_key, key_ok := os.LookupEnv("SCAN_KEY")
Expand Down
3 changes: 3 additions & 0 deletions vingo/template.env
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
CORS_ALLOW_ORIGINS=
DEVELOPMENT

ZAUTH_URL=
ZAUTH_CALLBACK_PATH=
ZAUTH_CLIENT_ID=
ZAUTH_CLIENT_SECRET=
ZAUTH_REDIRECT_URI=
Expand Down
Loading
Loading