diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index f950e5d..21ddba5 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -184,5 +184,27 @@ jobs: file: Dockerfile-RustBuildEnvArm64 push: true tags: danstaken/rust-build-env-arm64:latest - platforms: linux/arm64 + platforms: linux/arm64 + + - name: Build and push multi-architecture Docker smithe-backend image + uses: docker/build-push-action@v5 + with: + context: . + file: Dockerfile-SmitheBackend + push: true + tags: danstaken/smithe-backend:latest + platforms: linux/arm64 + + - name: Build and push multi-architecture Docker smithe-frontend image + uses: docker/build-push-action@v5 + with: + context: . + file: Dockerfile-SmitheFrontend + push: true + tags: danstaken/smithe-frontend:latest + platforms: linux/arm64 + build-args: | + SERVER_ADDRESS=${{ secrets.SERVER_ADDRESS_KUBERNETES }} + RECAPTCHA_SITE_KEY=${{ secrets.RECAPTCHA_SITE_KEY }} + SERVER_ADDRESS_2=${{ secrets.SERVER_ADDRESS_2 }} diff --git a/Dockerfile-SmitheBackend b/Dockerfile-SmitheBackend new file mode 100644 index 0000000..d93be86 --- /dev/null +++ b/Dockerfile-SmitheBackend @@ -0,0 +1,13 @@ +FROM rust:latest + +# Set the working directory in the container +WORKDIR /usr/src/smithereens + +# Copy the entire workspace +COPY . . + +# Build the project +RUN cargo build --release --package smithe_backend + +# Specify the command to run the binary +CMD ["./target/release/smithe_backend"] \ No newline at end of file diff --git a/Dockerfile-SmitheFrontend b/Dockerfile-SmitheFrontend new file mode 100644 index 0000000..4e741c2 --- /dev/null +++ b/Dockerfile-SmitheFrontend @@ -0,0 +1,23 @@ +FROM rust:latest AS builder + +# Define build-time variables +ARG SERVER_ADDRESS +ARG RECAPTCHA_SITE_KEY +ARG SERVER_ADDRESS_2 + +WORKDIR /usr/src/smithereens +COPY . . + +# Set environment variables for build +ENV SERVER_ADDRESS=${SERVER_ADDRESS} +ENV RECAPTCHA_SITE_KEY=${RECAPTCHA_SITE_KEY} +ENV SERVER_ADDRESS_2=${SERVER_ADDRESS_2} + +# Add wasm32-unknown-unix to the toolchain +RUN rustup target add wasm32-unknown-unknown + +RUN cargo install trunk +RUN trunk build ./frontend/index.html --release + +FROM nginx:alpine +COPY --from=builder /usr/src/smithereens/frontend/dist /usr/share/nginx/html diff --git a/Makefile b/Makefile index 18f274e..511d2a4 100644 --- a/Makefile +++ b/Makefile @@ -38,6 +38,50 @@ buildx-rsbuildenvarm64: buildx-pidgtm: docker buildx build --platform linux/arm64 -t danstaken/pidgtm:latest -f Dockerfile-Pidgtm --push . +.PHONY: buildx-backend +buildx-backend: + docker buildx build --platform linux/arm64 -t danstaken/smithe-backend:latest -f Dockerfile-SmitheBackend --push . + +.PHONY: buildx-frontend +buildx-frontend: + docker buildx build --platform linux/arm64 -t danstaken/smithe-frontend:latest -f Dockerfile-SmitheFrontend --push . + +# KUBERNETES +.PHONY: install-cert-manager +install-cert-manager: + kubectl apply -f https://github.com/jetstack/cert-manager/releases/latest/download/cert-manager.yaml + +.PHONY: create-clusterissuer +create-clusterissuer: + kubectl apply -f ./clusterissuer.yml + +.PHONY: install-nginx-ingress + kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/1bc745619d91b690c8985bbc16097e9fe804d2d2/deploy/static/provider/cloud/deploy.yaml + +.PHONY: get-ingress-ip +get-ingress-ip: + kubectl get services -o wide -n ingress-nginx + # ^^^ look for the EXTERNAL_IP to setup DNS + +.PHONY: setup-backend-secrets +setup-backend-secrets: + kubectl create secret generic backend-secrets --from-env-file=backend-secrets.env + +.PHONY: deploy-backend +deploy-backend: + # setup-backend-secrets (done) + kubectl apply -f ./backend-deployment.yml + kubectl apply -f ./backend-service.yml + +.PHONY: deploy-frontend +deploy-frontend: + # install-cert-manager (done) + # create-clusterissuer (done) + # install-nginx-ingress (to do) + kubectl apply -f ./frontend-deployment.yml + kubectl apply -f ./frontend-service.yml + kubectl apply -f ./frontend-ingress.yml + # PIDGTM .PHONY: pidgtm pidgtm-map: diff --git a/backend-deployment.yml b/backend-deployment.yml new file mode 100644 index 0000000..4c46c09 --- /dev/null +++ b/backend-deployment.yml @@ -0,0 +1,31 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: backend-deployment +spec: + replicas: 3 + selector: + matchLabels: + app: backend + template: + metadata: + labels: + app: backend + spec: + containers: + - name: backend + image: danstaken/smithe-backend:latest + imagePullPolicy: Always + ports: + - containerPort: 8000 + env: + - name: PIDGTM_DATABASE_URL + valueFrom: + secretKeyRef: + name: backend-secrets + key: PIDGTM_DATABASE_URL + - name: STARTGG_TOKEN + valueFrom: + secretKeyRef: + name: backend-secrets + key: STARTGG_TOKEN diff --git a/backend-service.yml b/backend-service.yml new file mode 100644 index 0000000..0468d50 --- /dev/null +++ b/backend-service.yml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Service +metadata: + name: backend-service +spec: + type: ClusterIP + selector: + app: backend + ports: + - protocol: TCP + port: 8000 + targetPort: 8000 diff --git a/backend/src/main.rs b/backend/src/main.rs index cd5d535..473e52d 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -20,6 +20,7 @@ use thiserror::Error; pub const DEV_ADDRESS: &str = "http://localhost:8080/"; pub const DEV_ADDRESS_2: &str = "http://127.0.0.1:8080/"; +pub const PROD_ADDRESS: &str = "https://smithe.net"; #[derive(Error, Debug)] pub enum Error { @@ -110,8 +111,12 @@ async fn get_player_head_to_head(id: i32) -> Result { } fn rocket() -> Rocket { + #[cfg(debug_assertions)] let allowed_origins = AllowedOrigins::some_exact(&[DEV_ADDRESS, DEV_ADDRESS_2]); + #[cfg(not(debug_assertions))] + let allowed_origins = AllowedOrigins::some_exact(&[PROD_ADDRESS]); + let cors = rocket_cors::CorsOptions { allowed_origins, allowed_methods: vec![Method::Get, Method::Post, Method::Delete, Method::Put] diff --git a/clusterissuer.yml b/clusterissuer.yml new file mode 100644 index 0000000..47dbeb9 --- /dev/null +++ b/clusterissuer.yml @@ -0,0 +1,18 @@ +apiVersion: cert-manager.io/v1 +kind: ClusterIssuer +metadata: + name: letsencrypt-prod +spec: + acme: + # The ACME server URL + server: https://acme-v02.api.letsencrypt.org/directory + # Email address used for ACME registration + email: danilochiarlone@hotmail.com + # Name of a secret used to store the ACME account private key + privateKeySecretRef: + name: letsencrypt-prod + # ACME DNS-01 provider configurations + solvers: + - http01: + ingress: + class: nginx \ No newline at end of file diff --git a/frontend-deployment.yml b/frontend-deployment.yml new file mode 100644 index 0000000..8eadd03 --- /dev/null +++ b/frontend-deployment.yml @@ -0,0 +1,20 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: frontend-deployment +spec: + replicas: 3 + selector: + matchLabels: + app: frontend + template: + metadata: + labels: + app: frontend + spec: + containers: + - name: frontend + image: danstaken/smithe-frontend:latest + imagePullPolicy: Always + ports: + - containerPort: 80 \ No newline at end of file diff --git a/frontend-ingress.yml b/frontend-ingress.yml new file mode 100644 index 0000000..b486460 --- /dev/null +++ b/frontend-ingress.yml @@ -0,0 +1,24 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: frontend-ingress + annotations: + nginx.ingress.kubernetes.io/rewrite-target: / + cert-manager.io/cluster-issuer: "letsencrypt-prod" + nginx.ingress.kubernetes.io/force-ssl-redirect: "true" +spec: + tls: + - hosts: + - smithe.net + secretName: smithe-net-tls + rules: + - host: smithe.net + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: frontend-service + port: + number: 80 \ No newline at end of file diff --git a/frontend-service.yml b/frontend-service.yml new file mode 100644 index 0000000..686a71c --- /dev/null +++ b/frontend-service.yml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Service +metadata: + name: frontend-service +spec: + type: LoadBalancer + selector: + app: frontend + ports: + - protocol: TCP + port: 80 + targetPort: 80 \ No newline at end of file