-
-
Notifications
You must be signed in to change notification settings - Fork 779
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
deploy open-saas on Google Cloud Platform (firebase + cloud run) #178
Comments
Optional, but if you need to see every steps as one big script I've made github actions for my CD. This might give a global overview of the steps to follow: backend-cd.yml name: Deploy to Cloud Run on merge
on:
push:
branches:
- main
jobs:
build_and_deploy_backend:
runs-on: ubuntu-latest
env:
# Env variables
GCP_PROJECT_ID: ${{ vars.GCP_PROJECT_ID }}
WASP_SERVER_URL_DEV: ${{ vars.WASP_SERVER_URL_DEV }}
WASP_WEB_CLIENT_URL_DEV: ${{ vars.WASP_WEB_CLIENT_URL_DEV }}
ADMIN_EMAILS_DEV: ${{ vars.ADMIN_EMAILS_DEV }}
# Secrets
DATABASE_URL_DEV: ${{ secrets.DATABASE_URL_DEV }}
SERVICE_ACCOUNT: ${{ secrets.SERVICE_ACCOUNT }}
GOOGLE_CLIENT_ID_DEV: ${{ secrets.GOOGLE_CLIENT_ID_DEV }}
GOOGLE_CLIENT_SECRET_DEV: ${{ secrets.GOOGLE_CLIENT_SECRET_DEV }}
HOBBY_SUBSCRIPTION_PRICE_ID_DEV: ${{ secrets.HOBBY_SUBSCRIPTION_PRICE_ID_DEV }}
PRO_SUBSCRIPTION_PRICE_ID_DEV: ${{ secrets.PRO_SUBSCRIPTION_PRICE_ID_DEV }}
SENDGRID_API_KEY_DEV: ${{ secrets.SENDGRID_API_KEY_DEV }}
STRIPE_KEY_DEV: ${{ secrets.STRIPE_KEY_DEV }}
STRIPE_WEBHOOK_SECRET_DEV: ${{ secrets.STRIPE_WEBHOOK_SECRET_DEV }}
JWT_SECRET_DEV: ${{ secrets.JWT_SECRET}}
steps:
- uses: actions/checkout@v4
- name: Build Docker Image
run: |
curl -sSL https://get.wasp-lang.dev/installer.sh | sh
cd app
wasp build
cd .wasp/build
docker build -t backend-image -f Dockerfile .
docker tag backend-image europe-west1-docker.pkg.dev/${{ env.GCP_PROJECT_ID }}/backend/backend-image:${{ github.sha }}
- name: Authenticate to GCP
uses: google-github-actions/auth@v1
with:
credentials_json: ${{ secrets.SERVICE_ACCOUNT }}
- name: Configure Docker
run: |
gcloud auth configure-docker europe-west1-docker.pkg.dev
- name: Push Docker Image
run: |
docker push europe-west1-docker.pkg.dev/${{ env.GCP_PROJECT_ID }}/backend/backend-image:${{ github.sha }}
- name: Deploy to Cloud Run
run: |
gcloud run deploy backend \
--image europe-west1-docker.pkg.dev/${{ env.GCP_PROJECT_ID }}/backend/backend-image:${{ github.sha }} \
--project ${{ env.GCP_PROJECT_ID }} \
--platform managed \
--region europe-west1 \
--max-instances 2 \
--min-instances 0 \
--allow-unauthenticated \
--set-env-vars "DATABASE_URL=${{ env.DATABASE_URL_DEV }}" \
--set-env-vars "STRIPE_KEY=${{ env.STRIPE_KEY_DEV }}" \
--set-env-vars "GOOGLE_CLIENT_ID=${{ env.GOOGLE_CLIENT_ID_DEV }}" \
--set-env-vars "GOOGLE_CLIENT_SECRET=${{ env.GOOGLE_CLIENT_SECRET_DEV }}" \
--set-env-vars "HOBBY_SUBSCRIPTION_PRICE_ID=${{ env.HOBBY_SUBSCRIPTION_PRICE_ID_DEV }}" \
--set-env-vars "PRO_SUBSCRIPTION_PRICE_ID=${{ env.PRO_SUBSCRIPTION_PRICE_ID_DEV }}" \
--set-env-vars "SENDGRID_API_KEY=${{ env.SENDGRID_API_KEY_DEV }}" \
--set-env-vars "STRIPE_WEBHOOK_SECRET=${{ env.STRIPE_WEBHOOK_SECRET_DEV }}" \
--set-env-vars "WASP_SERVER_URL=${{ env.WASP_SERVER_URL_DEV }}" \
--set-env-vars "WASP_WEB_CLIENT_URL=${{ env.WASP_WEB_CLIENT_URL_DEV }}" \
--set-env-vars "ADMIN_EMAILS=${{ env.ADMIN_EMAILS_DEV }}" \
--set-env-vars "JWT_SECRET=${{ env.JWT_SECRET_DEV }}" frontend-cd.yml name: Deploy to Firebase Hosting on merge
on:
push:
branches:
- main
jobs:
build_and_deploy_frontend:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: |
curl -sSL https://get.wasp-lang.dev/installer.sh | sh
cd app
wasp build
cd .wasp/build/web-app
npm install
REACT_APP_API_URL=${{ vars.WASP_SERVER_URL_DEV }}
npm run build
- uses: FirebaseExtended/action-hosting-deploy@v0
with:
repoToken: ${{ secrets.GITHUB_TOKEN }}
firebaseServiceAccount: ${{ secrets.SERVICE_ACCOUNT }}
channelId: live
projectId: ${{ vars.GCP_PROJECT_ID }} |
This is awesome, thanks @TomDarmon ! We can use this as a good foundation for writing the docs for deploying to GCP. CI action is also quite useful! |
While Firebase does offer a way to rewrite routes to send all requests to e.g. |
Related convo on the Discord: https://discord.com/channels/686873244791210014/1249887793082138758/1249887793082138758 |
Hello, I've recently gone through the steps to deploy open-saas on GCP and I believe it could be useful to document it here for now.
This could be added to the real documentation in the future, for now I'll just detail what I did to make it work.
A few prerequisites:
• Have a GCP account & project with billing enabled (you might succeed without, but that's what I had).
• Successfully run the open-saas template locally with, the appropriate env variable and an emailSender not set to Dummy.
Step 1 - GCP & firebase setup:
First, login to GCP and populate the default credentials. This step is important, it will ensure you don't get access issues.
Run the 2 command separately and login each time:
gcloud auth login
gcloud auth application-default login
In your GCP project, enable the needed APIs:
We will be building our Docker image and storing it in GCP, therefore we need to create an artifact registry where we will push the image:
For the firebase setup:
Step 2 - Deploy the frontend with firebase hosting
Follow the step 1 and 3 to get the build of the frontend (give a fake REACT_APP_API_URL for now, since we don't have it yet) --> https://wasp-lang.dev/docs/0.11.8/advanced/deployment/manually#1-generating-deployable-code
Add this firebase.json and .firebashrc at the root of your repo, optionally you can put them elsewhere but you need to adapt the paths and where you will run the firebase commands:
firebase.json
.firebaserc
Now you are ready to deploy the frontend:
npm install -g firebase-tools
firebase login
firebase deploy --only hosting
--> Do this from the root of the repo if you did place the firebase.json at root and didn't change any pathStep 3 - Deploy the backend with cloud run
Cloud run expects the container service to be exposed on port 8080, this cannot be changed. So we need to find a way to do this, luckily the wasp team enabled us to overwrite the Dockerfile server entry point and add any steps ! See the doc --> https://wasp-lang.dev/docs/advanced/deployment/overview#customizing-the-dockerfile
Create a Dockerfile at ./app/Dockerfile
Now you need to do a
wasp build
again with this setup to update the Dockerfile under .wasp/build/Dockerfile.After the wasp build command, you can check that the new Dockerfile has indeed your added steps in it.
Build the image and push it to Artifact Registry. I will use the Docker Artifact Registry I created in step 1 but adapt it to the one you created:
Once the image is successfully uploaded to artifact registry, you can deploy your backlend with:
You will receive a made up backend URL, for example
https://backend-feiufeaoa-ew.a.run.app
Step 4 - Link the frontend and backend
You now have all the elements, you just need to piece it together:
REACT_APP_API_URL
set to your backend URL (https://backend-feiufeaoa-ew.a.run.app)WASP_SERVER_URL
env variable of your backend to the real one (https://backend-feiufeaoa-ew.a.run.app)You can go back to your frontend under https://{FILL_YOUR_FULL__GCP_PROJECT_NAME}.web.app and check that everything works.
The backend URL is a bit ugly, additionally it is not under the same domain so you might run under CORS issues. Firebase offers automatic redirect to the cloud run backend directly from your website, I still need to crack that part !
The text was updated successfully, but these errors were encountered: