For production or cloud usage, we recommend deploying the Docker container to Google Cloud Run. This guide walks you through:
- Creating a new (or using an existing) Cloud SQL for MySQL instance
- Setting up a dedicated user and database
- Building and pushing your Docker image
- Deploying to Cloud Run
- Verifying everything works end-to-end
- Google Cloud CLI (
gcloud
) – installed and authenticated to your GCP project (gcloud auth login
). - Cloud Run enabled in your GCP project.
- Docker – for building the container image locally (you can also use GitHub Actions to build it).
This repository includes a sample Dockerfile:
FROM node:20-alpine
# Install nginx (optional)
RUN apk add --no-cache --update nginx && \
chown -R nginx:www-data /var/lib/nginx
COPY ./nginx.conf /etc/nginx/nginx.conf
EXPOSE 8080
WORKDIR /app
COPY . .
RUN npm i knex -g && \
npm run build
# By default, node out/src/index.js. It will conditionally run Nginx if NODE_ENV != development
CMD [ "node", "out/src/index.js"]
Note: If you prefer to skip Nginx in production, you can remove the RUN apk add ...
line and any references to nginx
. By default, index.ts
spawns Nginx only if NODE_ENV !== 'development'
.
If you already have a MySQL instance set up, skip to Step 3.
Otherwise, create a new instance:
gcloud sql instances create my-wallet-sql-instance \
--database-version=MYSQL_8_0 \
--tier=db-f1-micro \
--region=us-west1 \
--authorized-networks=0.0.0.0/0
Configuring authorized-networks
like this allows all traffic by default. (This may not be recommended for production, so adjust accordingly.)
Adjust parameters (machine type, region) as needed. Then set a root password:
gcloud sql users set-password root \
--host=% \
--instance=my-wallet-sql-instance \
--password=YOUR_SECURE_PASSWORD
Once your MySQL instance is up, create your primary database. You can do this with one of the following:
gcloud sql connect my-wallet-sql-instance --user=root
When prompted, enter your root password. Then in the MySQL shell:
CREATE DATABASE wallet_storage;
SHOW DATABASES; -- optional, to verify it exists
- Connect to your Cloud SQL instance (or local instance) using host, port, and credentials.
- Run
CREATE DATABASE wallet_storage;
.
For better security, create and grant privileges to a non-root user (e.g., wallet_admin
).
-
Create a user (outside the MySQL shell):
gcloud sql users create wallet_admin \ --instance=my-wallet-sql-instance \ --password=ANOTHER_SECURE_PASSWORD
-
Grant privileges on the
wallet_storage
database. First connect with root:gcloud sql connect my-wallet-sql-instance --user=root
Then in the MySQL shell:
GRANT ALL PRIVILEGES ON wallet_storage.* TO 'wallet_admin'@'%'; FLUSH PRIVILEGES; EXIT;
-
Use
wallet_admin
in your connection settings rather thanroot
, e.g.:{ "host": "PUBLIC_IP_OR_SOCKET_PATH_OF_YOUR_INSTANCE", "user": "wallet_admin", "password": "ANOTHER_SECURE_PASSWORD", "database": "wallet_storage", "port": 3306 }
Verify you can connect to your MySQL instance using the credentials you plan to provide to Cloud Run:
- Public IP: If using a public IP for Cloud SQL, ensure any required network settings (firewall rules, SSL, etc.) are in place.
- Private IP or Sockets: If using private IP or Unix sockets, read Cloud SQL + Cloud Run docs for the correct
host
orsocketPath
syntax.
Example valid JSON for an environment variable:
{
"host": "PUBLIC_IP_OF_YOUR_INSTANCE",
"user": "wallet_admin",
"password": "ANOTHER_SECURE_PASSWORD",
"database": "wallet_storage",
"port": 3306
}
If you can connect via a local MySQL client (such as MySQLWorkbench) using these credentials, you should be good to go.
Install and build local dependencies (the Dockerfile will copy over node_modules):
npm install
npm run build
From your project’s root folder:
docker build --platform linux/amd64 -t gcr.io/PROJECT_ID/utxo-management-server:latest .
Replace PROJECT_ID
with your actual Google Cloud project ID.
If you are unsure what your PROJECT_ID
is, you can use the following command to list the available projects:
gcloud projects list
docker push gcr.io/PROJECT_ID/utxo-management-server:latest
Before deploying, create an env.yaml file in your local directory to store environment variables:
NODE_ENV: "production"
BSV_NETWORK: "main" # main | test
ENABLE_NGINX: "true"
HTTP_PORT: "8080"
SERVER_PRIVATE_KEY: "<PRIVATE_KEY_HEX_STRING>"
KNEX_DB_CONNECTION: '{"host": "<HOST>", "user": "wallet_admin", "password": "<ANOTHER_SECURE_PASS>", "database": "wallet_storage", "port": 3306}'
Update the example environment values as needed.
You may also want to include env.yaml
in your .gitignore to prevent committing environment secrets.
NODE_ENV=production
: Ensures production settings (e.g., mainnet chian).ENABLE_NGINX=true
: By default, GCR limits requests to 32mb. When an nginx proxy is combined with the HTTP/2 passthrough on GCR, it increases the request size allowed.HTTP_PORT=8080
: Cloud Run default.SERVER_PRIVATE_KEY
: Your server’s private key for authenticating requests (do not include quotes).KNEX_DB_CONNECTION
: Must be a valid JSON string (a string representation of a JSON object). When defined in env.yaml, it should be enclosed in single quotes to ensure YAML treats it as a string.
Then deploy your image using:
gcloud run deploy utxo-management-server \
--image=gcr.io/PROJECT_ID/utxo-management-server:latest \
--region=us-west1 \
--platform=managed \
--allow-unauthenticated \
--env-vars-file=env.yaml
You can add --use-http2
, if you want your container to see full HTTP/2 requests (especially relevant if you’re doing streaming gRPC or advanced HTTP/2 features in Nginx).
- Wait for Cloud Run to finish deploying and note the service URL.
Ex.
Service [utxo-management-server] revision [utxo-management-server-00004-6n3] has been deployed and is serving 100 percent of traffic.
Service URL: https://utxo-management-server-131201068103.us-west1.run.app
- Open the Cloud Run URL in your browser (or use
curl
). - Check logs in the Cloud Run Console to confirm:
- Service started without errors.
- Migrations succeeded, creating the required tables in
wallet_storage
.
You can also confirm table creation by connecting to your DB and running:
SHOW TABLES;
That’s it! You have now:
- Created or connected to a MySQL instance (Cloud SQL or otherwise).
- Created a
wallet_storage
database. - Configured environment variables in Cloud Run to point to that database.
- Deployed your Docker container to Cloud Run.
Your UTXO Management Server should now be ready to handle requests. If you run into any database connectivity issues, double-check your connection string, credentials, and Cloud SQL networking/security settings.
- Connect your BSV wallet client to the new Cloud Run endpoint (the remote storage URL).
- Customize monetization, mutual auth, or additional route controllers as needed.
- Add a CI/CD pipeline for automated builds and deployments.
You can automate Docker builds and GCR deployments using GitHub Actions:
-
Add your GitHub secrets:
GCP_PROJECT_ID
GCP_SA_KEY
(service account JSON)KNEX_DB_CONNECTION
SERVER_PRIVATE_KEY
-
Create a
.github/workflows/deploy.yaml
:name: Deploy to Cloud Run on: push: branches: [ "master" ] jobs: build-and-deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Authenticate to Google Cloud uses: google-github-actions/auth@v1 with: credentials_json: ${{ secrets.GCP_SA_KEY }} - name: Configure docker run: gcloud auth configure-docker - name: Build run: | docker build --platform linux/amd64 -t gcr.io/${{ secrets.GCP_PROJECT_ID }}/utxo-management-server:${{ github.sha }} . - name: Push Docker image run: | docker push gcr.io/${{ secrets.GCP_PROJECT_ID }}/utxo-management-server:${{ github.sha }} - name: Deploy run: | gcloud run deploy utxo-management-server \ --image gcr.io/${{ secrets.GCP_PROJECT_ID }}/utxo-management-server:${{ github.sha }} \ --region=us-west1 \ --platform=managed \ --allow-unauthenticated \ --use-http2 \ --env-vars-file=env.yaml
Whenever you push to master
, this workflow will build, push, and deploy automatically.
You now have a production-ready UTXO Management Server running on Cloud Run and connected to a secure MySQL database. For further customization or troubleshooting:
- Check the Cloud SQL MySQL docs and Cloud Run docs.
- Review and tweak environment variables, server code, or Nginx configurations as desired.
Enjoy building on the BSV Blockchain with a robust wallet infrastructure!