<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Google Cloud Platform &#8211; My Shitty Code</title>
	<atom:link href="https://myshittycode.com/tag/google-cloud-platform/feed/" rel="self" type="application/rss+xml" />
	<link>https://myshittycode.com</link>
	<description>Embracing the Messiness in Search of Epic Solutions</description>
	<lastBuildDate>Thu, 08 Aug 2024 22:05:49 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.1</generator>

<image>
	<url>https://myshittycode.com/wp-content/uploads/2022/04/cropped-icon-32x32.png</url>
	<title>Google Cloud Platform &#8211; My Shitty Code</title>
	<link>https://myshittycode.com</link>
	<width>32</width>
	<height>32</height>
</image> 
<site xmlns="com-wordpress:feed-additions:1">205304208</site>	<item>
		<title>Cloud Run: Connecting to Cloud SQL with Private IP and SSL</title>
		<link>https://myshittycode.com/2024/08/08/cloud-run-connecting-to-cloud-sql-with-private-ip-and-ssl/</link>
					<comments>https://myshittycode.com/2024/08/08/cloud-run-connecting-to-cloud-sql-with-private-ip-and-ssl/#respond</comments>
		
		<dc:creator><![CDATA[Shitty Author]]></dc:creator>
		<pubDate>Thu, 08 Aug 2024 22:05:43 +0000</pubDate>
				<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Programming Language]]></category>
		<category><![CDATA[Cloud Run]]></category>
		<category><![CDATA[Cloud SQL]]></category>
		<category><![CDATA[Docker]]></category>
		<category><![CDATA[Google Cloud Platform]]></category>
		<category><![CDATA[Python]]></category>
		<guid isPermaLink="false">https://myshittycode.com/?p=2642</guid>

					<description><![CDATA[<p>There are various ways for a Cloud Run instance to connect to a Cloud SQL instance. Regardless of the solutions, if both resources reside in the same GCP organization, connecting using a Cloud SQL&#8217;s private IP with SSL/TLS encryption is highly recommended to prevent network traffic from going out to the internet. It is possible [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://myshittycode.com/2024/08/08/cloud-run-connecting-to-cloud-sql-with-private-ip-and-ssl/">Cloud Run: Connecting to Cloud SQL with Private IP and SSL</a> appeared first on <a rel="nofollow" href="https://myshittycode.com">My Shitty Code</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<div class="wp-block-rank-math-toc-block" id="rank-math-toc"><h2>Table of Contents</h2><nav><ul><li><a href="#cloud-sql-configuration">Cloud SQL Configuration</a></li><li><a href="#options">Options</a><ul><li><a href="#option-a-cloud-sql-language-connectors">Option A: Cloud SQL Language Connectors</a></li><li><a href="#option-b-managed-cloud-sql-proxy-in-cloud-run">Option B: Managed Cloud SQL Proxy in Cloud Run</a></li><li><a href="#option-c-manually-configure-cloud-sql-proxy">Option C: Manually Configure Cloud SQL Proxy</a></li><li><a href="#option-d-use-cloud-sq-ls-private-ip-and-client-certificate">Option D: Use Cloud SQL&#8217;s Private IP and Client Certificate</a></li></ul></li><li><a href="#recommendations">Recommendations</a><ul><li><a href="#best-solution-option-a">Best Solution &#8211; Option A</a></li><li><a href="#distance-next-best-solution-option-d">Distance Next Best Solution &#8211; Option D</a></li><li><a href="#least-favorite-solution-option-b-c">Least Favorite Solution &#8211; Option B &amp; C</a></li></ul></li></ul></nav></div>



<p>There are various ways for a Cloud Run instance to connect to a Cloud SQL instance. Regardless of the solutions, if both resources reside in the same GCP organization, connecting using a Cloud SQL&#8217;s private IP with SSL/TLS encryption is highly recommended to prevent network traffic from going out to the internet.</p>



<p>It is possible to have a Cloud SQL instance with both private and public IPs enabled, and there are legitimate reasons for doing so. For example, it allows the developers to connect to the Cloud SQL instance outside the GCP environment. However, utmost care is needed to ensure the private IP is always used when connecting from the Cloud Run instance.</p>



<p>This article evaluates the pros and cons of each solution and provides some recommendations.</p>



<h2 class="wp-block-heading" id="cloud-sql-configuration">Cloud SQL Configuration</h2>



<p>For consistency&#8217;s sake, SSL/TLS encryption is enabled on the Cloud SQL instance using client certificates.</p>



<figure class="wp-block-image size-large is-resized"><img fetchpriority="high" decoding="async" width="1024" height="742" src="https://myshittycode.com/wp-content/uploads/2024/08/ssl-mode-1-1024x742.png?x45560" alt="Cloud SQL" class="wp-image-2651" style="width:800px" srcset="https://myshittycode.com/wp-content/uploads/2024/08/ssl-mode-1-1024x742.png 1024w, https://myshittycode.com/wp-content/uploads/2024/08/ssl-mode-1-300x217.png 300w, https://myshittycode.com/wp-content/uploads/2024/08/ssl-mode-1-768x557.png 768w, https://myshittycode.com/wp-content/uploads/2024/08/ssl-mode-1.png 1104w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>A client certificate is also created. </p>



<figure class="wp-block-image size-large is-resized"><img decoding="async" width="1024" height="417" src="https://myshittycode.com/wp-content/uploads/2024/08/client-certificate-1-1024x417.png?x45560" alt="" class="wp-image-2650" style="width:800px" srcset="https://myshittycode.com/wp-content/uploads/2024/08/client-certificate-1-1024x417.png 1024w, https://myshittycode.com/wp-content/uploads/2024/08/client-certificate-1-300x122.png 300w, https://myshittycode.com/wp-content/uploads/2024/08/client-certificate-1-768x313.png 768w, https://myshittycode.com/wp-content/uploads/2024/08/client-certificate-1.png 1096w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p><strong>Note:</strong> Some solutions, such as Cloud SQL Proxy and Cloud SQL Language Connectors, do not need the client certificate. So, these steps can be safely skipped. From the <a href="https://cloud.google.com/sql/docs/mysql/configure-ssl-instance#enforcing-ssl" target="_blank" rel="noopener">documentation</a>:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>With Cloud SQL Auth Proxy and Cloud SQL Connectors, client and server identities are also automatically verified regardless of the SSL mode setting.</p>
</blockquote>



<h2 class="wp-block-heading" id="options">Options</h2>



<h3 class="wp-block-heading" id="option-a-cloud-sql-language-connectors">Option A: Cloud SQL Language Connectors</h3>



<p>This solution uses <a href="https://cloud.google.com/sql/docs/mysql/connect-connectors" target="_blank" rel="noopener">Cloud SQL Language Connectors</a>, a programming language library maintained by Google.</p>



<p>The following configurations are <strong>NOT</strong> required:</p>



<ul class="wp-block-list">
<li>SSL certificates in the Cloud SQL instance</li>



<li>Cloud SQL volume mounting in the Cloud Run instance.</li>
</ul>



<p><strong>Python App</strong></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: python; title: ; notranslate">
import os

from google.cloud.sql.connector import Connector, IPTypes

# ... simplified for brevity

connector = Connector(IPTypes.PRIVATE)  # use Private IP

connector.connect(
  os.getenv(&#039;DB_INSTANCE_CONNECTION_NAME&#039;),  # project:region:instance
  &#039;pymysql&#039;,
  user=os.getenv(&#039;DB_USER&#039;),
  password=os.getenv(&#039;DB_PASS&#039;),
  db=os.getenv(&#039;DB_NAME&#039;),
)
</pre></div>


<p><strong>Pros</strong></p>



<ul class="wp-block-list">
<li>Very concise configuration in both IaC and application code since there&#8217;s no need to manage client certificates.</li>
</ul>



<p><strong>Cons</strong></p>



<ul class="wp-block-list">
<li>Only supports Python, Java, Go, and Node.js.</li>
</ul>



<h3 class="wp-block-heading" id="option-b-managed-cloud-sql-proxy-in-cloud-run">Option B: Managed Cloud SQL Proxy in Cloud Run</h3>



<p>This solution uses a <a href="https://cloud.google.com/sql/docs/mysql/connect-run#configure" target="_blank" rel="noopener">managed Cloud SQL Proxy</a> that is configurable directly in the Cloud Run instance. Once configured, a Cloud SQL volume mount is created in the Cloud Run instance. </p>



<p><strong>Python App</strong></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: python; title: ; notranslate">
import os

import pymysql

# ... simplified for brevity

pymysql.connect(
  database=os.getenv(&#039;DB_NAME&#039;),
  user=os.getenv(&#039;DB_USER&#039;),
  password=os.getenv(&#039;DB_PASS&#039;),
  unix_socket=f&#039;/cloudsql/{os.getenv(&quot;DB_INSTANCE_CONNECTION_NAME&quot;)}&#039;,  # /cloudsql/project:region:instance
)
</pre></div>


<p><strong>Pros</strong></p>



<ul class="wp-block-list">
<li>Very concise configuration in both IaC and application code since there&#8217;s no need to manage SSL certificates.</li>
</ul>



<p><strong>Cons</strong></p>



<ul class="wp-block-list">
<li><strong>It doesn&#8217;t work if the Cloud SQL instance has both public IP and private IP enabled</strong>. There&#8217;s no way to specify which IP to use, and Cloud SQL Proxy automatically uses the public IP if it exists.
<ul class="wp-block-list">
<li><strong>Note:</strong> If you know how to pull this off, please drop a comment below.</li>
</ul>
</li>



<li><a href="https://cloud.google.com/sql/docs/mysql/sql-proxy#production-environment" target="_blank" rel="noopener">Additional configurations</a> must be considered when running in production, which introduces many points of failure.</li>



<li>It may exceed the default <a href="https://cloud.google.com/sql/docs/mysql/connect-run#api-quota-limits" target="_blank" rel="noopener">Cloud SQL Admin API quota limit</a>.</li>
</ul>



<h3 class="wp-block-heading" id="option-c-manually-configure-cloud-sql-proxy">Option C: Manually Configure Cloud SQL Proxy</h3>



<p>This solution <a href="https://cloud.google.com/sql/docs/mysql/connect-auth-proxy" target="_blank" rel="noopener">manually configures Cloud SQL Proxy</a> via Dockerfile instead of relying on the managed Cloud SQL volume mount from Cloud Run.</p>



<p><strong>Dockerfile</strong></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; highlight: [13,14,16]; title: ; notranslate">
FROM python:3.12-alpine

RUN apk update &amp;amp;&amp;amp; apk add curl

WORKDIR /app

COPY . /app

RUN pip install --no-cache-dir -r requirements.txt

EXPOSE 8080

RUN curl -o cloud-sql-proxy https://storage.googleapis.com/cloud-sql-connectors/cloud-sql-proxy/v2.12.0/cloud-sql-proxy.linux.amd64
RUN chmod +x cloud-sql-proxy

CMD &#x5B;&quot;sh&quot;, &quot;-c&quot;, &quot;./cloud-sql-proxy --private-ip --port 3306 ${DB_INSTANCE_CONNECTION_NAME} &amp;amp; sleep 5 &amp;amp;&amp;amp; python app.py&quot;]
</pre></div>


<p><strong>Python App</strong></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: python; title: ; notranslate">
import os

import pymysql

# ... simplified for brevity

pymysql.connect(
  host=os.getenv(&#039;DB_HOST&#039;),  # 127.0.0.1
  database=os.getenv(&#039;DB_NAME&#039;),
  user=os.getenv(&#039;DB_USER&#039;),
  password=os.getenv(&#039;DB_PASS&#039;),
)
</pre></div>


<p><strong>Pros</strong></p>



<ul class="wp-block-list">
<li>Very concise configuration in both IaC and application code since there&#8217;s no need to manage client certificates.</li>



<li>Unlike the managed Cloud SQL Proxy volume mount solution, this solution will work even if the Cloud SQL instance has both private and public IPs.</li>
</ul>



<p><strong>Cons</strong></p>



<ul class="wp-block-list">
<li>Need to manage the Cloud SQL Proxy installation and configuration in the Dockerfile.</li>



<li>All the cons described in the managed Cloud SQL Proxy solution above still apply here.</li>
</ul>



<h3 class="wp-block-heading" id="option-d-use-cloud-sq-ls-private-ip-and-client-certificate">Option D: Use Cloud SQL&#8217;s Private IP and Client Certificate</h3>



<p>Instead of relying on external tools/libraries, the application code connects directly to the Cloud SQL instance using the private IP where the client certificate is also provided.</p>



<p><strong>Python App</strong></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: python; title: ; notranslate">
import os

import pymysql

# ... simplified for brevity

pymysql.connect(
  host=os.getenv(&#039;DB_HOST&#039;), # Cloud SQL&#039;s Private IP
  database=os.getenv(&#039;DB_NAME&#039;),
  user=os.getenv(&#039;DB_USER&#039;),
  password=os.getenv(&#039;DB_PASS&#039;),
  ssl={
    &#039;ca&#039;: os.getenv(&#039;DB_SSL_SERVER_CA&#039;),     # /app/certs/ca/server-ca.pem
    &#039;cert&#039;: os.getenv(&#039;DB_SSL_CLIENT_CERT&#039;), # /app/certs/cert/client-cert.pem
    &#039;key&#039;: os.getenv(&#039;DB_SSL_CLIENT_KEY&#039;),   # /app/certs/key/client-key.pem
    &#039;check_hostname&#039;: False,
  }
)
</pre></div>


<p><strong>Note:</strong> The hostname checking must be disabled because the database host (Cloud SQL&#8217;s Private IP) will never<br>match the common name specified in the certificate. If the hostname checking is not disabled, it will produce the following error:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>Error connecting to database: (2003, &#8220;Can&#8217;t connect to MySQL server on &#8217;10.x.x.x&#8217; ([SSL: CERTIFICATE_VERIFY_FAILED]<br>certificate verify failed: IP address mismatch, certificate is not valid for &#8217;10.x.x.x&#8217;. (_ssl.c:1000))&#8221;)</p>
</blockquote>



<p><strong>Pros</strong></p>



<ul class="wp-block-list">
<li>No additional wrappers like Cloud SQL Proxy or Cloud SQL Language Connectors are required.</li>
</ul>



<p><strong>Cons</strong></p>



<ul class="wp-block-list">
<li>Additional configurations and complexity on the IaC and application code are needed to manage and ingest the client certificate securely.</li>
</ul>



<h2 class="wp-block-heading" id="recommendations">Recommendations</h2>



<h3 class="wp-block-heading" id="best-solution-option-a">Best Solution &#8211; Option A</h3>



<p>Use Cloud SQL Language Connectors if your app uses one of the supported programming languages (Python, Java, Go, or Node.js). </p>



<p>It eliminates many unnecessary configurations on the IaC code and application code. In other words, there&#8217;s no need to do the following:</p>



<ul class="wp-block-list">
<li>Create a client certificate for Cloud SQL.</li>



<li>Store server certificate, client certificate, and client key in Secret Manager securely.</li>



<li>Mount files containing the server certificate, client certificate, and client key as volumes in the Cloud Run instance.</li>



<li>Pass certificate information to the application code via environment variables. </li>
</ul>



<p>None of the above is needed. </p>



<p>Less codebase = Less chance of errors.</p>



<h3 class="wp-block-heading" id="distance-next-best-solution-option-d">Distance Next Best Solution &#8211; Option D</h3>



<p>Connect directly using the Cloud SQL instance&#8217;s Private IP and client certificate.</p>



<p>It eliminates the need to rely on additional cloud configuration or external library (i.e., fewer points of failure). </p>



<p>However, it introduces additional configurations in IaC and application code to maintain and ingest the certificate described above.</p>



<h3 class="wp-block-heading" id="least-favorite-solution-option-b-c">Least Favorite Solution &#8211; Option B &amp; C</h3>



<p>While both Cloud SQL Proxy solutions (volume mount in the Cloud Run instance or installing it directly via Dockerfile) don&#8217;t require a client certificate, they come with <a href="https://cloud.google.com/sql/docs/mysql/sql-proxy#production-environment" target="_blank" rel="noopener">additional considerations and complexities when running in production</a>. </p>



<p>Furthermore, the volume mount solution won&#8217;t work if the Cloud SQL instance has both private and public IPs. </p>
<p>The post <a rel="nofollow" href="https://myshittycode.com/2024/08/08/cloud-run-connecting-to-cloud-sql-with-private-ip-and-ssl/">Cloud Run: Connecting to Cloud SQL with Private IP and SSL</a> appeared first on <a rel="nofollow" href="https://myshittycode.com">My Shitty Code</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://myshittycode.com/2024/08/08/cloud-run-connecting-to-cloud-sql-with-private-ip-and-ssl/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2642</post-id>	</item>
		<item>
		<title>Supercharge Docker Build Pipeline by 97%</title>
		<link>https://myshittycode.com/2024/03/21/supercharge-docker-build-pipeline/</link>
					<comments>https://myshittycode.com/2024/03/21/supercharge-docker-build-pipeline/#respond</comments>
		
		<dc:creator><![CDATA[Shitty Author]]></dc:creator>
		<pubDate>Thu, 21 Mar 2024 14:26:02 +0000</pubDate>
				<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Development Tools]]></category>
		<category><![CDATA[Artifact Registry]]></category>
		<category><![CDATA[Cloud Build]]></category>
		<category><![CDATA[Docker]]></category>
		<category><![CDATA[Google Cloud Platform]]></category>
		<guid isPermaLink="false">https://myshittycode.com/?p=2568</guid>

					<description><![CDATA[<p>This tutorial shows how to improve the performance of the remote pipeline that builds a Docker image using docker build, which takes 15 minutes to 20 seconds. Note: Although Google&#8217;s Cloud Build is used here, this solution can be applied in GitHub Actions, Azure Pipeline, or any pipeline-driven Docker builds. The Challenge with Docker Build [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://myshittycode.com/2024/03/21/supercharge-docker-build-pipeline/">Supercharge Docker Build Pipeline by 97%</a> appeared first on <a rel="nofollow" href="https://myshittycode.com">My Shitty Code</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<div class="wp-block-rank-math-toc-block" id="rank-math-toc"><h2>Table of Contents</h2><nav><ul><li><a href="#the-challenge-with-docker-build">The Challenge with Docker Build</a></li><li><a href="#solution">Solution</a><ul><li><a href="#introducing-buildx">Introducing Buildx</a></li><li><a href="#step-1-enable-experimental-mode">Step 1: Enable experimental mode</a></li><li><a href="#step-2-specify-build-driver">Step 2: Specify build driver</a></li><li><a href="#step-3-configure-build-caches">Step 3: Configure build caches</a></li><li><a href="#step-4-putting-everything-together">Step 4: Putting everything together</a></li><li><a href="#step-5-analyze-build-results">Step 5: Analyze build results</a></li><li><a href="#step-6-verify-image-repository">Step 6: Verify image repository</a></li></ul></li></ul></nav></div>



<p>This tutorial shows how to improve the performance of the remote pipeline that builds a Docker image using <strong>docker build</strong>, which takes 15 minutes to 20 seconds.</p>



<p><strong>Note:</strong> Although Google&#8217;s Cloud Build is used here, this solution can be applied in GitHub Actions, Azure Pipeline, or any pipeline-driven Docker builds.</p>



<h2 class="wp-block-heading" id="the-challenge-with-docker-build">The Challenge with Docker Build</h2>



<p>Given the following Google&#8217;s Cloud Build script:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: yaml; title: ; notranslate">
# cloudbuild.yml

steps:
  - name: gcr.io/cloud-builders/docker
    args: &#x5B;&quot;build&quot;, &quot;-t&quot;, &quot;${_NAME}&quot;, &quot;.&quot;]

images:
  - ${_NAME}

substitutions:
  _LOCATION: us-central1
  _REPO: shared
  _IMAGE: chatbot
  _NAME: ${_LOCATION}-docker.pkg.dev/${PROJECT_ID}/${_REPO}/${_IMAGE}

options:
  logging: CLOUD_LOGGING_ONLY
  machineType: E2_HIGHCPU_32
  dynamicSubstitutions: true
</pre></div>


<p>When kicking off the build&#8230;</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
gcloud builds submit --config=cloudbuild.yml --project=&#x5B;PROJECT ID]
</pre></div>


<p>&#8230; Docker builds the image successfully and pushes it to the Artifact Registry.</p>



<p>When rerunning the same build multiple times, it takes similar time to run:</p>



<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="192" src="https://myshittycode.com/wp-content/uploads/2024/03/docker-build-before-1-1024x192.png?x45560" alt="" class="wp-image-2570" srcset="https://myshittycode.com/wp-content/uploads/2024/03/docker-build-before-1-1024x192.png 1024w, https://myshittycode.com/wp-content/uploads/2024/03/docker-build-before-1-300x56.png 300w, https://myshittycode.com/wp-content/uploads/2024/03/docker-build-before-1-768x144.png 768w, https://myshittycode.com/wp-content/uploads/2024/03/docker-build-before-1.png 1346w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>In the example above, building the image with no changes to the Dockerfile takes an average of 15 minutes.</p>



<h2 class="wp-block-heading" id="solution">Solution</h2>



<p>When running the build locally, Docker takes advantage of the layer caching by storing the data in the file system. This results in faster subsequent builds. </p>



<p>However, when using a remote pipeline, the agent assigned to the pipeline job is ephemeral. Hence, Docker must always rebuild all layers, resulting in a long build time. To fix this annoyance, we must instruct Docker to cache the layers elsewhere. </p>



<h3 class="wp-block-heading" id="introducing-buildx">Introducing Buildx</h3>



<p>Docker has a relatively unheard CLI command called Buildx that allows the layers to be cached remotely. <a href="https://docs.docker.com/build/architecture/" target="_blank" rel="noopener">Buildx has been the default build client</a> since Docker Engine 23.0 and Docker Desktop 4.19.</p>



<p>To investigate, run the following commands locally to verify:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; highlight: [5]; title: ; notranslate">
$ docker --version
Docker version 25.0.3, build 4debf41

$ docker build --help
Usage:  docker buildx build &#x5B;OPTIONS] PATH | URL | -

// TRUNCATED
</pre></div>


<h3 class="wp-block-heading" id="step-1-enable-experimental-mode">Step 1: Enable experimental mode</h3>



<p>At the time of writing, Google&#8217;s Cloud Build uses a Docker version older than v23.0.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="180" src="https://myshittycode.com/wp-content/uploads/2024/03/cloudbuild-docker-version-1024x180.png?x45560" alt="" class="wp-image-2576" srcset="https://myshittycode.com/wp-content/uploads/2024/03/cloudbuild-docker-version-1024x180.png 1024w, https://myshittycode.com/wp-content/uploads/2024/03/cloudbuild-docker-version-300x53.png 300w, https://myshittycode.com/wp-content/uploads/2024/03/cloudbuild-docker-version-768x135.png 768w, https://myshittycode.com/wp-content/uploads/2024/03/cloudbuild-docker-version.png 1396w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Hence, an environment variable must be set to enable the experimental mode when using an older Docker version.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: yaml; highlight: [7,8]; title: ; notranslate">
# cloudbuild.yml

options:
  logging: CLOUD_LOGGING_ONLY
  machineType: E2_HIGHCPU_32
  dynamicSubstitutions: true
  env:
    - DOCKER_CLI_EXPERIMENTAL=enabled
</pre></div>


<h3 class="wp-block-heading" id="step-2-specify-build-driver">Step 2: Specify build driver</h3>



<p>A different Docker driver must be explicitly specified to use the layer caching feature in the older Docker version.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: yaml; title: ; notranslate">
# cloudbuild.yml

steps:
  - name: gcr.io/cloud-builders/docker
    entrypoint: bash
    args:
      - -c
      - &gt;-
        docker buildx create
        --driver docker-container
        --use
</pre></div>


<h3 class="wp-block-heading" id="step-3-configure-build-caches">Step 3: Configure build caches</h3>



<p>Now, configure Docker to fetch and store the caches.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: yaml; title: ; notranslate">
# cloudbuild.yml

steps:
  # ...

  - name: gcr.io/cloud-builders/docker
    entrypoint: bash
    args:
      - -c
      - &gt;-
        docker buildx build
        --cache-from ${_NAME}:cache
        --cache-to type=registry,ref=${_NAME}:cache,mode=max
        -t ${_NAME} .
        --push
</pre></div>


<p>In this example, the cache image is stored in the same image repository in Artifact Registry but with a different tag, <strong>cache</strong>.</p>



<p>To ensure all layers&#8217; build information is cached, <strong>mode=max</strong> is specified, too.</p>



<h3 class="wp-block-heading" id="step-4-putting-everything-together">Step 4: Putting everything together</h3>



<p>The modified build file looks like this:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: yaml; title: ; notranslate">
# cloudbuild.yml

steps:
  - name: gcr.io/cloud-builders/docker
    entrypoint: bash
    args:
      - -c
      - &gt;-
        docker buildx create
        --driver docker-container
        --use

  - name: gcr.io/cloud-builders/docker
    entrypoint: bash
    args:
      - -c
      - &gt;-
        docker buildx build
        --cache-from ${_NAME}:cache
        --cache-to type=registry,ref=${_NAME}:cache,mode=max
        -t ${_NAME} .
        --push

substitutions:
  _LOCATION: us-central1
  _REPO: shared
  _IMAGE: chatbot
  _NAME: ${_LOCATION}-docker.pkg.dev/${PROJECT_ID}/${_REPO}/${_IMAGE}

options:
  logging: CLOUD_LOGGING_ONLY
  machineType: E2_HIGHCPU_32
  dynamicSubstitutions: true
  env:
    - DOCKER_CLI_EXPERIMENTAL=enabled
</pre></div>


<h3 class="wp-block-heading" id="step-5-analyze-build-results">Step 5: Analyze build results</h3>



<p>Now, submit the build multiple times to examine the results.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="232" src="https://myshittycode.com/wp-content/uploads/2024/03/docker-build-after-1024x232.png?x45560" alt="" class="wp-image-2580" srcset="https://myshittycode.com/wp-content/uploads/2024/03/docker-build-after-1024x232.png 1024w, https://myshittycode.com/wp-content/uploads/2024/03/docker-build-after-300x68.png 300w, https://myshittycode.com/wp-content/uploads/2024/03/docker-build-after-768x174.png 768w, https://myshittycode.com/wp-content/uploads/2024/03/docker-build-after.png 1352w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>The build logs show that the first run takes about 12 minutes because the cache has yet to exist. Once the cache exists, the subsequent build takes an average of 20 seconds.</p>



<p>The reason for the gap between 4 PM and 7 PM was that nobody had the time to sit for 12 minutes for the build to finish.</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="543" height="460" src="https://myshittycode.com/wp-content/uploads/2024/03/beer.jpg?x45560" alt="" class="wp-image-2581" srcset="https://myshittycode.com/wp-content/uploads/2024/03/beer.jpg 543w, https://myshittycode.com/wp-content/uploads/2024/03/beer-300x254.jpg 300w" sizes="auto, (max-width: 543px) 100vw, 543px" /></figure>



<h3 class="wp-block-heading" id="step-6-verify-image-repository">Step 6: Verify image repository</h3>



<p>The images stored in the Artifact Registry look like this:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="483" src="https://myshittycode.com/wp-content/uploads/2024/03/image-artifact-registry-1-1024x483.png?x45560" alt="" class="wp-image-2589" srcset="https://myshittycode.com/wp-content/uploads/2024/03/image-artifact-registry-1-1024x483.png 1024w, https://myshittycode.com/wp-content/uploads/2024/03/image-artifact-registry-1-300x142.png 300w, https://myshittycode.com/wp-content/uploads/2024/03/image-artifact-registry-1-768x363.png 768w, https://myshittycode.com/wp-content/uploads/2024/03/image-artifact-registry-1-1536x725.png 1536w, https://myshittycode.com/wp-content/uploads/2024/03/image-artifact-registry-1.png 1716w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>As you can see, the final image (with the <strong>latest</strong> tag) and the cache image (with the <strong>cache</strong> tag) are successfully stored in the Artifact Registry. The 20-second build is exclusively spent pulling a few gigabytes of cache image from the Artifact Registry.</p>
<p>The post <a rel="nofollow" href="https://myshittycode.com/2024/03/21/supercharge-docker-build-pipeline/">Supercharge Docker Build Pipeline by 97%</a> appeared first on <a rel="nofollow" href="https://myshittycode.com">My Shitty Code</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://myshittycode.com/2024/03/21/supercharge-docker-build-pipeline/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2568</post-id>	</item>
		<item>
		<title>Rclone: Backing Up Synology NAS to GCP</title>
		<link>https://myshittycode.com/2023/10/03/rclone-backing-up-synology-nas-to-gcp/</link>
					<comments>https://myshittycode.com/2023/10/03/rclone-backing-up-synology-nas-to-gcp/#respond</comments>
		
		<dc:creator><![CDATA[Shitty Author]]></dc:creator>
		<pubDate>Tue, 03 Oct 2023 14:29:13 +0000</pubDate>
				<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Server]]></category>
		<category><![CDATA[Google Cloud Platform]]></category>
		<category><![CDATA[Google Cloud Storage]]></category>
		<category><![CDATA[Rclone]]></category>
		<category><![CDATA[Synology NAS]]></category>
		<guid isPermaLink="false">https://myshittycode.com/?p=2396</guid>

					<description><![CDATA[<p>This post shows how you can use Rclone to back up your data from a Synology NAS to a storage bucket in GCP. Why Backing Up Synology NAS Backing up data is like wearing a seat belt when driving, where nothing bad happens 99% of the time. However, when the 1% strikes unexpectedly one day, [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://myshittycode.com/2023/10/03/rclone-backing-up-synology-nas-to-gcp/">Rclone: Backing Up Synology NAS to GCP</a> appeared first on <a rel="nofollow" href="https://myshittycode.com">My Shitty Code</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<div class="wp-block-rank-math-toc-block" id="rank-math-toc"><h2>Table of Contents</h2><nav><ul><li><a href="#why-backing-up-synology-nas">Why Backing Up Synology NAS</a></li><li><a href="#why-rclone">Why Rclone</a></li><li><a href="#why-gcp">Why GCP</a></li><li><a href="#configuration">Configuration</a><ul><li><a href="#setting-up-gcp-resources">Setting up GCP Resources</a></li><li><a href="#setting-up-rclone-in-synology-nas">Setting Up Rclone in Synology NAS</a><ul><li><a href="#ways-to-install-rclone">Ways to Install Rclone</a></li><li><a href="#whats-in-docker-appdata-rclone">What&#8217;s in /docker/appdata/rclone</a></li><li><a href="#downloading-docker-image">Downloading Docker Image</a></li><li><a href="#creating-docker-container-with-dry-run">Creating Docker Container (with &#8211;dry-run)</a></li><li><a href="#creating-docker-container-without-dry-run">Creating Docker Container (without &#8211;dry-run)</a></li><li><a href="#scheduling-docker-container-to-run">Scheduling Docker Container to Run</a></li></ul></li></ul></li></ul></nav></div>



<p>This post shows how you can use Rclone to back up your data from a Synology NAS to a storage bucket in GCP.</p>



<h2 class="wp-block-heading" id="why-backing-up-synology-nas">Why Backing Up Synology NAS</h2>



<p>Backing up data is like wearing a seat belt when driving, where nothing bad happens 99% of the time. However, when the 1% strikes unexpectedly one day, the &#8220;future&#8221; you will be grateful that you do not lose any precious data, such as childhood photos, important documents, etc. </p>



<p>When you own several machines at home, it makes sense to centralize the shared data in a local NAS, such as Synology NAS. You may also configure Time Machine to seamlessly back up each Mac to Synology NAS every weekend. It is equally important to back up the data in Synology NAS to the cloud. Your car&#8217;s seat belt might be faulty, but you still have an airbag. If a thief breaks into your house, steals your shiny NAS, and burns your house down, you still have your data in the cloud. </p>



<p>The moral of the story is always to back up your data, preferably using the <a href="https://www.cisa.gov/sites/default/files/publications/data_backup_options.pdf" target="_blank" rel="noopener">3-2-1 rule</a>.</p>



<h2 class="wp-block-heading" id="why-rclone">Why Rclone</h2>



<p>The most confusing part of the Synology NAS backup process is there are several ways to do this. The three popular solutions are <a href="https://www.synology.com/en-global/dsm/feature/cloud_sync" target="_blank" rel="noopener">Cloud Sync</a>, <a href="https://www.synology.com/en-global/dsm/feature/hyper_backup" target="_blank" rel="noopener">Hyper Backup</a>, and <a href="https://rclone.org/" target="_blank" rel="noopener">Rclone</a>. Each solution allows us to push data to various cloud providers. This <a href="https://www.reddit.com/r/synology/comments/hsy29y/hyper_backup_vs_cloud_sync_vs_rclone/" target="_blank" rel="noopener">Reddit post</a> nicely sums it all up. If I can summarize the most significant disadvantage of each solution in a few words, it will be:</p>



<ul class="wp-block-list">
<li>Cloud Sync silently ignores file names with unsupported characters.</li>



<li>Hyper Backup landlocks you to Synology solution because you can&#8217;t browse the backed-up files in the cloud.</li>



<li>Rclone doesn&#8217;t have a pretty GUI.</li>
</ul>



<p>Rclone seems more palatable among these solutions because I know all my data will be backed up. When disaster strikes next time, I also don&#8217;t have to deal with the proprietary format during my data recovery process. Who knows if Synology will still be around 20 years from now?</p>



<h2 class="wp-block-heading" id="why-gcp">Why GCP</h2>



<p>In the past, I configured my Synology NAS to perform a seamless backup to <a href="https://www.crashplan.com/en-us/" target="_blank" rel="noopener">CrashPlan</a> using <a href="https://hub.docker.com/r/jlesage/crashplan-pro" target="_blank" rel="noopener">this Docker solution</a>. It has worked flawlessly for many years. The main reasons I want to move the backups to my personal GCP org are:</p>



<ul class="wp-block-list">
<li>I have free GCP credits. Even without the GCP credits, based on <a href="https://cloud.google.com/products/calculator" target="_blank" rel="noopener">the GCP Pricing Calculator</a>, it is still cheaper to back up my data to a regional <a href="https://cloud.google.com/storage/docs/storage-classes#classes" target="_blank" rel="noopener">Archive storage</a> bucket than CrashPlan.</li>



<li>I can customize the number of backup versions and retention policies.</li>



<li>It is faster to recover all my data if needed.</li>



<li>I want to secure the data and GCP resources myself.</li>
</ul>



<p>You can swap out GCP with a cloud provider of your choice. For example, you can use Rclone to back up all your photos to <a href="https://www.amazon.com/b/?node=15547130011" target="_blank" rel="noopener">Amazon Photos</a> for free if you have a Prime membership and your <a href="https://www.amazon.com/gp/help/customer/display.html?nodeId=GGU2SU8Y22DZYRMQ" target="_blank" rel="noopener">photo formats are supported</a>. My RAW images (supported) also have corresponding XMP files (not supported), and I want to back up other file formats too.</p>



<h2 class="wp-block-heading" id="configuration">Configuration</h2>



<p>This diagram below helps you to visualize the solution.</p>



<figure class="wp-block-image aligncenter size-large"><img loading="lazy" decoding="async" width="1024" height="514" src="https://myshittycode.com/wp-content/uploads/2023/08/synology-to-gcp-1-1024x514.png?x45560" alt="Synology NAS" class="wp-image-2418" srcset="https://myshittycode.com/wp-content/uploads/2023/08/synology-to-gcp-1-1024x514.png 1024w, https://myshittycode.com/wp-content/uploads/2023/08/synology-to-gcp-1-300x151.png 300w, https://myshittycode.com/wp-content/uploads/2023/08/synology-to-gcp-1-768x386.png 768w, https://myshittycode.com/wp-content/uploads/2023/08/synology-to-gcp-1.png 1312w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<h3 class="wp-block-heading" id="setting-up-gcp-resources">Setting up GCP Resources</h3>



<p>The best way to secure the data backups is to create a separate GCP project where only a specific service account has sufficient permission to write to a storage bucket. At a high level:</p>



<ul class="wp-block-list">
<li>Create a GCP project.</li>



<li>Create a storage bucket.
<ul class="wp-block-list">
<li>Enable object versioning and limit them to N versions (to prevent rising storage costs).</li>
</ul>
</li>



<li>Create a service account.</li>



<li>Grant service account with Storage Object Admin (roles/storage.objectAdmin) at the project level.</li>



<li>Create a service account key.</li>



<li>Download the service account key file in JSON format to the local machine first. In this post, this file is named <strong>service-account.json</strong>.</li>



<li><strong>BONUS</strong>: If you are paranoid, <a href="https://myshittycode.com/2023/08/18/vpc-sc-2-ways-to-fix-no_matching_access_level-error/" data-type="post" data-id="2359">configure a VPC Service Control perimeter and put that project within the perimeter</a>. This ensures only the whitelisted IPs can access these project resources. This way, even if the service account key is compromised, adversaries cannot access the protected resources unless they also spoof the IPs.</li>
</ul>



<h3 class="wp-block-heading" id="setting-up-rclone-in-synology-nas">Setting Up Rclone in Synology NAS</h3>



<h4 class="wp-block-heading" id="ways-to-install-rclone">Ways to Install Rclone</h4>



<p>There are multiple ways to install Rclone in Synology NAS:</p>



<ul class="wp-block-list">
<li><a href="https://rclone.org/install/" target="_blank" rel="noopener">Install Rclone</a> directly in Synology NAS.</li>



<li>Install Rclone using Docker (<a href="https://hub.docker.com/r/rclone/rclone" target="_blank" rel="noopener">rclone/rclone</a>).</li>



<li>Install Rclone with GUI using Docker (<a href="https://hub.docker.com/r/romancin/rclonebrowser" target="_blank" rel="noopener">romancin/rclonebrowser</a>).</li>
</ul>



<p>In this post, I use the second solution (without GUI) because simpler implementation means less chance of the tool breaking in the future. Besides, this is a &#8220;set-and-forget&#8221; process, and I don&#8217;t need to use the GUI most of the time.</p>



<h4 class="wp-block-heading" id="whats-in-docker-appdata-rclone">What&#8217;s in /docker/appdata/rclone</h4>



<p>/docker/appdata should already exist when the Docker package is installed in Synology NAS. You only need to create a child folder named <strong>rclone</strong> (or any name you like). This folder contains three files:</p>



<ul class="wp-block-list">
<li><strong>excludes.txt</strong> = File patterns to be excluded from the backup process.</li>



<li><strong>rclone.conf</strong> = Rclone configuration.</li>



<li><strong>service-account.json</strong> = The service account key file that you downloaded to your local machine from GCP.</li>
</ul>



<p>Here&#8217;s my example of <strong>excludes.txt</strong>, and customize it to your needs:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
@eaDir/**
.**
</pre></div>


<p><strong>rclone.conf</strong> can be generated using <strong>rclone config</strong> command. However, that must be done outside Synology NAS (i.e., on your local machine). That said, most of this command&#8217;s interactive steps are unnecessary since you created the storage bucket earlier. All you need is exactly this and nothing else:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
&#x5B;gcp]
type = google cloud storage
service_account_file = /config/rclone/service-account.json
</pre></div>


<h4 class="wp-block-heading" id="downloading-docker-image">Downloading Docker Image</h4>



<p>Go to <strong>DSM</strong> &gt; <strong>Docker</strong> to download rclone/rclone image. </p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="586" src="https://myshittycode.com/wp-content/uploads/2023/10/1-download-image-1024x586.png?x45560" alt="" class="wp-image-2504" srcset="https://myshittycode.com/wp-content/uploads/2023/10/1-download-image-1024x586.png 1024w, https://myshittycode.com/wp-content/uploads/2023/10/1-download-image-300x172.png 300w, https://myshittycode.com/wp-content/uploads/2023/10/1-download-image-768x440.png 768w, https://myshittycode.com/wp-content/uploads/2023/10/1-download-image-1536x880.png 1536w, https://myshittycode.com/wp-content/uploads/2023/10/1-download-image.png 1966w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<h4 class="wp-block-heading" id="creating-docker-container-with-dry-run">Creating Docker Container (with &#8211;dry-run)</h4>



<p>This step ensures the Rclone is configured properly before any files are copied to the storage bucket to prevent incurring unnecessary costs.</p>



<p>First, create a new container.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="584" src="https://myshittycode.com/wp-content/uploads/2023/10/2-container-create-1024x584.png?x45560" alt="" class="wp-image-2505" srcset="https://myshittycode.com/wp-content/uploads/2023/10/2-container-create-1024x584.png 1024w, https://myshittycode.com/wp-content/uploads/2023/10/2-container-create-300x171.png 300w, https://myshittycode.com/wp-content/uploads/2023/10/2-container-create-768x438.png 768w, https://myshittycode.com/wp-content/uploads/2023/10/2-container-create-1536x876.png 1536w, https://myshittycode.com/wp-content/uploads/2023/10/2-container-create.png 1968w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Use rclone/rclone image.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="588" src="https://myshittycode.com/wp-content/uploads/2023/10/3-container-image-1024x588.png?x45560" alt="" class="wp-image-2506" srcset="https://myshittycode.com/wp-content/uploads/2023/10/3-container-image-1024x588.png 1024w, https://myshittycode.com/wp-content/uploads/2023/10/3-container-image-300x172.png 300w, https://myshittycode.com/wp-content/uploads/2023/10/3-container-image-768x441.png 768w, https://myshittycode.com/wp-content/uploads/2023/10/3-container-image-1536x881.png 1536w, https://myshittycode.com/wp-content/uploads/2023/10/3-container-image.png 1966w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>No changes to the network settings.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="589" src="https://myshittycode.com/wp-content/uploads/2023/10/4-container-network-1024x589.png?x45560" alt="" class="wp-image-2507" srcset="https://myshittycode.com/wp-content/uploads/2023/10/4-container-network-1024x589.png 1024w, https://myshittycode.com/wp-content/uploads/2023/10/4-container-network-300x173.png 300w, https://myshittycode.com/wp-content/uploads/2023/10/4-container-network-768x442.png 768w, https://myshittycode.com/wp-content/uploads/2023/10/4-container-network-1536x884.png 1536w, https://myshittycode.com/wp-content/uploads/2023/10/4-container-network.png 1968w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Enter the container name, and go to <strong>Advanced Settings</strong>.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="589" src="https://myshittycode.com/wp-content/uploads/2023/10/5-container-general-settings-1024x589.png?x45560" alt="" class="wp-image-2508" srcset="https://myshittycode.com/wp-content/uploads/2023/10/5-container-general-settings-1024x589.png 1024w, https://myshittycode.com/wp-content/uploads/2023/10/5-container-general-settings-300x172.png 300w, https://myshittycode.com/wp-content/uploads/2023/10/5-container-general-settings-768x441.png 768w, https://myshittycode.com/wp-content/uploads/2023/10/5-container-general-settings-1536x883.png 1536w, https://myshittycode.com/wp-content/uploads/2023/10/5-container-general-settings.png 1966w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Under <strong>Execution Command</strong>, enter the following command:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
sync /data gcp:&#x5B;BUCKET_NAME] --exclude-from /config/rclone/excludes.txt --gcs-bucket-policy-only --verbose --dry-run
</pre></div>


<p>Replace <strong>[BUCKET_NAME]</strong> with your own bucket name.</p>



<p><strong>IMPORTANT:</strong> Synology does not allow us to edit the execution command after creating a container!</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="584" src="https://myshittycode.com/wp-content/uploads/2023/10/6-container-advanced-settings-1-1024x584.png?x45560" alt="" class="wp-image-2531" srcset="https://myshittycode.com/wp-content/uploads/2023/10/6-container-advanced-settings-1-1024x584.png 1024w, https://myshittycode.com/wp-content/uploads/2023/10/6-container-advanced-settings-1-300x171.png 300w, https://myshittycode.com/wp-content/uploads/2023/10/6-container-advanced-settings-1-768x438.png 768w, https://myshittycode.com/wp-content/uploads/2023/10/6-container-advanced-settings-1-1536x876.png 1536w, https://myshittycode.com/wp-content/uploads/2023/10/6-container-advanced-settings-1.png 1970w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>No changes to the port settings.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="588" src="https://myshittycode.com/wp-content/uploads/2023/10/7-container-port-settings-1024x588.png?x45560" alt="" class="wp-image-2510" srcset="https://myshittycode.com/wp-content/uploads/2023/10/7-container-port-settings-1024x588.png 1024w, https://myshittycode.com/wp-content/uploads/2023/10/7-container-port-settings-300x172.png 300w, https://myshittycode.com/wp-content/uploads/2023/10/7-container-port-settings-768x441.png 768w, https://myshittycode.com/wp-content/uploads/2023/10/7-container-port-settings-1536x882.png 1536w, https://myshittycode.com/wp-content/uploads/2023/10/7-container-port-settings.png 1964w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Define the volume mounts:</p>



<ul class="wp-block-list">
<li>/config/rclone = contains the Rclone configuration files.</li>



<li>/data = contains data to be backed up.
<ul class="wp-block-list">
<li>Because you can&#8217;t perform a volume mount on root /, each root folder needs to be volume-mounted to a subfolder within /data that you wish to back up.</li>
</ul>
</li>
</ul>



<p><strong>TIP:</strong> Consider mounting a data folder with the least amount of data when doing the dry run test. You can add/remove folders on an existing container later.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="587" src="https://myshittycode.com/wp-content/uploads/2023/10/8-container-volume-settings-1024x587.png?x45560" alt="" class="wp-image-2511" srcset="https://myshittycode.com/wp-content/uploads/2023/10/8-container-volume-settings-1024x587.png 1024w, https://myshittycode.com/wp-content/uploads/2023/10/8-container-volume-settings-300x172.png 300w, https://myshittycode.com/wp-content/uploads/2023/10/8-container-volume-settings-768x440.png 768w, https://myshittycode.com/wp-content/uploads/2023/10/8-container-volume-settings-1536x881.png 1536w, https://myshittycode.com/wp-content/uploads/2023/10/8-container-volume-settings.png 1964w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Review the summary.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="588" src="https://myshittycode.com/wp-content/uploads/2023/10/9-container-summary-1024x588.png?x45560" alt="" class="wp-image-2512" srcset="https://myshittycode.com/wp-content/uploads/2023/10/9-container-summary-1024x588.png 1024w, https://myshittycode.com/wp-content/uploads/2023/10/9-container-summary-300x172.png 300w, https://myshittycode.com/wp-content/uploads/2023/10/9-container-summary-768x441.png 768w, https://myshittycode.com/wp-content/uploads/2023/10/9-container-summary-1536x882.png 1536w, https://myshittycode.com/wp-content/uploads/2023/10/9-container-summary.png 1964w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Once the container is created, click on the toggle to run it.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="585" src="https://myshittycode.com/wp-content/uploads/2023/10/10-container-created-1024x585.png?x45560" alt="" class="wp-image-2513" srcset="https://myshittycode.com/wp-content/uploads/2023/10/10-container-created-1024x585.png 1024w, https://myshittycode.com/wp-content/uploads/2023/10/10-container-created-300x172.png 300w, https://myshittycode.com/wp-content/uploads/2023/10/10-container-created-768x439.png 768w, https://myshittycode.com/wp-content/uploads/2023/10/10-container-created-1536x878.png 1536w, https://myshittycode.com/wp-content/uploads/2023/10/10-container-created.png 1966w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Review the container log. You can drop a few files into the mounted folder and rerun the container. The files should show up in the log.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="633" src="https://myshittycode.com/wp-content/uploads/2023/10/11-container-run-log-1024x633.png?x45560" alt="" class="wp-image-2514" srcset="https://myshittycode.com/wp-content/uploads/2023/10/11-container-run-log-1024x633.png 1024w, https://myshittycode.com/wp-content/uploads/2023/10/11-container-run-log-300x185.png 300w, https://myshittycode.com/wp-content/uploads/2023/10/11-container-run-log-768x475.png 768w, https://myshittycode.com/wp-content/uploads/2023/10/11-container-run-log-1536x949.png 1536w, https://myshittycode.com/wp-content/uploads/2023/10/11-container-run-log.png 1854w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<h4 class="wp-block-heading" id="creating-docker-container-without-dry-run">Creating Docker Container (without &#8211;dry-run)</h4>



<p>Now that you have a working container to perform the dry run test, it&#8217;s time to back up the data to the cloud.</p>



<p>As mentioned earlier, it is not possible to edit the existing container&#8217;s execution command. The existing container contains the <strong>&#8211;dry-run</strong> flag on the execution command. The simplest way is to export the container setting, which will be used to create a new container without the <strong>&#8211;dry-run</strong> flag.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="585" src="https://myshittycode.com/wp-content/uploads/2023/10/12-container-export-1024x585.png?x45560" alt="" class="wp-image-2515" srcset="https://myshittycode.com/wp-content/uploads/2023/10/12-container-export-1024x585.png 1024w, https://myshittycode.com/wp-content/uploads/2023/10/12-container-export-300x171.png 300w, https://myshittycode.com/wp-content/uploads/2023/10/12-container-export-768x439.png 768w, https://myshittycode.com/wp-content/uploads/2023/10/12-container-export-1536x877.png 1536w, https://myshittycode.com/wp-content/uploads/2023/10/12-container-export.png 1972w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Export just the container settings to a local machine.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="585" src="https://myshittycode.com/wp-content/uploads/2023/10/13-container-export-local-1024x585.png?x45560" alt="" class="wp-image-2516" srcset="https://myshittycode.com/wp-content/uploads/2023/10/13-container-export-local-1024x585.png 1024w, https://myshittycode.com/wp-content/uploads/2023/10/13-container-export-local-300x172.png 300w, https://myshittycode.com/wp-content/uploads/2023/10/13-container-export-local-768x439.png 768w, https://myshittycode.com/wp-content/uploads/2023/10/13-container-export-local-1536x878.png 1536w, https://myshittycode.com/wp-content/uploads/2023/10/13-container-export-local.png 1966w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Open the JSON file, locate and remove <strong>&#8211;dry-run</strong> from <strong>cmd</strong>. Save the file.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; highlight: [4]; title: ; notranslate">
{
   &quot;CapAdd&quot; : &#x5B;],
   &quot;CapDrop&quot; : &#x5B;],
   &quot;cmd&quot; : &quot;sync /data gcp:&#x5B;BUCKET_NAME] --exclude-from /config/rclone/excludes.txt --gcs-bucket-policy-only --verbose --dry-run&quot;,
   &quot;cpu_priority&quot; : 0,
   &quot;enable_publish_all_ports&quot; : false,
   ...
}
</pre></div>


<p>Return to the Docker container window to import this JSON file to create a new container.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="582" src="https://myshittycode.com/wp-content/uploads/2023/10/14-container-import-1024x582.png?x45560" alt="" class="wp-image-2517" srcset="https://myshittycode.com/wp-content/uploads/2023/10/14-container-import-1024x582.png 1024w, https://myshittycode.com/wp-content/uploads/2023/10/14-container-import-300x171.png 300w, https://myshittycode.com/wp-content/uploads/2023/10/14-container-import-768x437.png 768w, https://myshittycode.com/wp-content/uploads/2023/10/14-container-import-1536x873.png 1536w, https://myshittycode.com/wp-content/uploads/2023/10/14-container-import.png 1966w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Upload the modified JSON file and provide a new container name.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="586" src="https://myshittycode.com/wp-content/uploads/2023/10/15-container-import-local-1024x586.png?x45560" alt="" class="wp-image-2518" srcset="https://myshittycode.com/wp-content/uploads/2023/10/15-container-import-local-1024x586.png 1024w, https://myshittycode.com/wp-content/uploads/2023/10/15-container-import-local-300x172.png 300w, https://myshittycode.com/wp-content/uploads/2023/10/15-container-import-local-768x440.png 768w, https://myshittycode.com/wp-content/uploads/2023/10/15-container-import-local-1536x879.png 1536w, https://myshittycode.com/wp-content/uploads/2023/10/15-container-import-local.png 1964w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Now, there are 2 Rclone containers: one with the <strong>&#8211;dry-run</strong> flag and another without it. It is up to you whether to retain or delete the container with the <strong>&#8211;dry-run</strong> flag. </p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="584" src="https://myshittycode.com/wp-content/uploads/2023/10/16-container-import-successful-1024x584.png?x45560" alt="" class="wp-image-2519" srcset="https://myshittycode.com/wp-content/uploads/2023/10/16-container-import-successful-1024x584.png 1024w, https://myshittycode.com/wp-content/uploads/2023/10/16-container-import-successful-300x171.png 300w, https://myshittycode.com/wp-content/uploads/2023/10/16-container-import-successful-768x438.png 768w, https://myshittycode.com/wp-content/uploads/2023/10/16-container-import-successful-1536x876.png 1536w, https://myshittycode.com/wp-content/uploads/2023/10/16-container-import-successful.png 1964w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<h4 class="wp-block-heading" id="scheduling-docker-container-to-run">Scheduling Docker Container to Run</h4>



<p>To ensure the Rclone runs to back up the files to the cloud, create a task scheduler. In this example, a triggered task is created so that Rclone can perform the backups on boot-up.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="575" src="https://myshittycode.com/wp-content/uploads/2023/10/17-scheduler-create-1024x575.png?x45560" alt="" class="wp-image-2520" srcset="https://myshittycode.com/wp-content/uploads/2023/10/17-scheduler-create-1024x575.png 1024w, https://myshittycode.com/wp-content/uploads/2023/10/17-scheduler-create-300x168.png 300w, https://myshittycode.com/wp-content/uploads/2023/10/17-scheduler-create-768x431.png 768w, https://myshittycode.com/wp-content/uploads/2023/10/17-scheduler-create-1536x862.png 1536w, https://myshittycode.com/wp-content/uploads/2023/10/17-scheduler-create.png 2024w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Ensure to run the task as root.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="574" src="https://myshittycode.com/wp-content/uploads/2023/10/18-scheduler-general-1024x574.png?x45560" alt="" class="wp-image-2521" srcset="https://myshittycode.com/wp-content/uploads/2023/10/18-scheduler-general-1024x574.png 1024w, https://myshittycode.com/wp-content/uploads/2023/10/18-scheduler-general-300x168.png 300w, https://myshittycode.com/wp-content/uploads/2023/10/18-scheduler-general-768x430.png 768w, https://myshittycode.com/wp-content/uploads/2023/10/18-scheduler-general-1536x860.png 1536w, https://myshittycode.com/wp-content/uploads/2023/10/18-scheduler-general.png 2028w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Specify the following script to execute. This script ensures the Docker service is running first before starting the container to perform the backup.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
while (synopkg status Docker | jq -r &#039;.status&#039; | grep -vq &quot;running&quot;); do
  sleep 10
done

docker container start rclone
</pre></div>


<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="575" src="https://myshittycode.com/wp-content/uploads/2023/10/19-scheduler-task-settings-1024x575.png?x45560" alt="" class="wp-image-2522" srcset="https://myshittycode.com/wp-content/uploads/2023/10/19-scheduler-task-settings-1024x575.png 1024w, https://myshittycode.com/wp-content/uploads/2023/10/19-scheduler-task-settings-300x168.png 300w, https://myshittycode.com/wp-content/uploads/2023/10/19-scheduler-task-settings-768x431.png 768w, https://myshittycode.com/wp-content/uploads/2023/10/19-scheduler-task-settings-1536x862.png 1536w, https://myshittycode.com/wp-content/uploads/2023/10/19-scheduler-task-settings.png 2028w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>That&#8217;s it! Every time the Synology NAS boots up, the Rclone container will run to perform any necessary data backup to the cloud.</p>
<p>The post <a rel="nofollow" href="https://myshittycode.com/2023/10/03/rclone-backing-up-synology-nas-to-gcp/">Rclone: Backing Up Synology NAS to GCP</a> appeared first on <a rel="nofollow" href="https://myshittycode.com">My Shitty Code</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://myshittycode.com/2023/10/03/rclone-backing-up-synology-nas-to-gcp/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2396</post-id>	</item>
		<item>
		<title>VPC SC: 2 Ways to Fix NO_MATCHING_ACCESS_LEVEL Error</title>
		<link>https://myshittycode.com/2023/08/18/vpc-sc-2-ways-to-fix-no_matching_access_level-error/</link>
					<comments>https://myshittycode.com/2023/08/18/vpc-sc-2-ways-to-fix-no_matching_access_level-error/#respond</comments>
		
		<dc:creator><![CDATA[Shitty Author]]></dc:creator>
		<pubDate>Fri, 18 Aug 2023 22:37:10 +0000</pubDate>
				<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Google Cloud Platform]]></category>
		<category><![CDATA[VPC SC]]></category>
		<guid isPermaLink="false">https://myshittycode.com/?p=2359</guid>

					<description><![CDATA[<p>This post shows you how to fix the dreaded NO_MATCHING_ACCESS_LEVEL error when dealing with VPC Service Control in GCP. Background Let&#8217;s assume you want to protect a project and its resources by putting it within a VPC SC perimeter. You must also ensure your trusted device(s) can access the protected project resources. In this case, [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://myshittycode.com/2023/08/18/vpc-sc-2-ways-to-fix-no_matching_access_level-error/">VPC SC: 2 Ways to Fix NO_MATCHING_ACCESS_LEVEL Error</a> appeared first on <a rel="nofollow" href="https://myshittycode.com">My Shitty Code</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<div class="wp-block-rank-math-toc-block" id="rank-math-toc"><h2>Table of Contents</h2><nav><ul><li><a href="#background">Background</a></li><li><a href="#problem">Problem</a></li><li><a href="#solution">Solution</a><ul><li><a href="#option-a-keep-existing-scoped-access-policy-create-dummy-unscoped-access-policy">Option A: Keep Existing Scoped Access Policy, Create Dummy Unscoped Access Policy</a></li><li><a href="#option-b-preferred-delete-existing-scoped-access-policy-create-unscoped-access-policy-with-vpc-sc-perimeter">Option B (Preferred): Delete Existing Scoped Access Policy, Create Unscoped Access Policy with VPC SC Perimeter</a></li></ul></li></ul></nav></div>



<p>This post shows you how to fix the dreaded NO_MATCHING_ACCESS_LEVEL error when dealing with VPC Service Control in GCP.</p>



<h2 class="wp-block-heading" id="background">Background</h2>



<p>Let&#8217;s assume you want to protect a project and its resources by putting it within a VPC SC perimeter. You must also ensure your trusted device(s) can access the protected project resources.</p>



<figure class="wp-block-image aligncenter size-large is-resized"><img decoding="async" src="https://myshittycode.com/wp-content/uploads/2023/08/vpc-sc-logical-diagram-1024x381.png?x45560" alt="" class="wp-image-2360" style="width:800px" width="800" srcset="https://myshittycode.com/wp-content/uploads/2023/08/vpc-sc-logical-diagram-1024x381.png 1024w, https://myshittycode.com/wp-content/uploads/2023/08/vpc-sc-logical-diagram-300x112.png 300w, https://myshittycode.com/wp-content/uploads/2023/08/vpc-sc-logical-diagram-768x286.png 768w, https://myshittycode.com/wp-content/uploads/2023/08/vpc-sc-logical-diagram.png 1187w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>In this case, an access level is created to capture the IP address (or CIDR ranges) that requires access to the protected resources.</p>



<figure class="wp-block-image aligncenter size-large is-resized"><img decoding="async" src="https://myshittycode.com/wp-content/uploads/2023/08/access-context-manager-1024x644.png?x45560" alt="" class="wp-image-2361" style="width:700px" width="700" srcset="https://myshittycode.com/wp-content/uploads/2023/08/access-context-manager-1024x644.png 1024w, https://myshittycode.com/wp-content/uploads/2023/08/access-context-manager-300x189.png 300w, https://myshittycode.com/wp-content/uploads/2023/08/access-context-manager-768x483.png 768w, https://myshittycode.com/wp-content/uploads/2023/08/access-context-manager.png 1056w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>Once an access level is created, a VPC SC perimeter is also created with the ingress policy configured to allow any identities from the whitelisted IPs access to the protected project resources. </p>



<figure class="wp-block-image aligncenter size-large"><img loading="lazy" decoding="async" width="454" height="1024" src="https://myshittycode.com/wp-content/uploads/2023/08/vpc-sc-perimeter-454x1024.png?x45560" alt="" class="wp-image-2362" srcset="https://myshittycode.com/wp-content/uploads/2023/08/vpc-sc-perimeter-454x1024.png 454w, https://myshittycode.com/wp-content/uploads/2023/08/vpc-sc-perimeter-133x300.png 133w, https://myshittycode.com/wp-content/uploads/2023/08/vpc-sc-perimeter-768x1733.png 768w, https://myshittycode.com/wp-content/uploads/2023/08/vpc-sc-perimeter-681x1536.png 681w, https://myshittycode.com/wp-content/uploads/2023/08/vpc-sc-perimeter.png 882w" sizes="auto, (max-width: 454px) 100vw, 454px" /></figure>



<h2 class="wp-block-heading" id="problem">Problem</h2>



<p>One easy way to test the VPC SC perimeter is to interact with a GCS bucket from the command line. If the perimeter is configured properly, you should see a list of files. Otherwise, you will get a VPC SC error like below.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
&gt; gsutil ls gs://my-shitty-bucket
AccessDeniedException: 403 Request is prohibited by organization&#039;s policy. 
vpcServiceControlsUniqueIdentifier: qQgF9j6AzA413Mfinr2fC5c67-TQoJRuNFKfCzAfXXXXXXXX
</pre></div>


<p>When looking up the VPC SC UID for more details, it states there is no matching access level, even though the VPC SC perimeter is configured with an access level containing a matching IP address.</p>



<figure class="wp-block-image aligncenter size-large"><img loading="lazy" decoding="async" width="946" height="1024" src="https://myshittycode.com/wp-content/uploads/2023/08/vpc-sc-troubleshooter-946x1024.png?x45560" alt="" class="wp-image-2363" srcset="https://myshittycode.com/wp-content/uploads/2023/08/vpc-sc-troubleshooter-946x1024.png 946w, https://myshittycode.com/wp-content/uploads/2023/08/vpc-sc-troubleshooter-277x300.png 277w, https://myshittycode.com/wp-content/uploads/2023/08/vpc-sc-troubleshooter-768x832.png 768w, https://myshittycode.com/wp-content/uploads/2023/08/vpc-sc-troubleshooter-1419x1536.png 1419w, https://myshittycode.com/wp-content/uploads/2023/08/vpc-sc-troubleshooter-1891x2048.png 1891w" sizes="auto, (max-width: 946px) 100vw, 946px" /></figure>



<h2 class="wp-block-heading" id="solution">Solution</h2>



<p>The most likely reason for this error is you have <a href="https://cloud.google.com/access-context-manager/docs/create-access-policy#scoped-access-policy" target="_blank" rel="noopener">accidentally created a scoped access policy</a> (see the red warning below) without an unscoped access policy at the org level.</p>



<figure class="wp-block-image aligncenter size-large is-resized"><img decoding="async" src="https://myshittycode.com/wp-content/uploads/2023/08/gcp-doc-1024x280.png?x45560" alt="" class="wp-image-2377" style="width:800px" width="800" srcset="https://myshittycode.com/wp-content/uploads/2023/08/gcp-doc-1024x280.png 1024w, https://myshittycode.com/wp-content/uploads/2023/08/gcp-doc-300x82.png 300w, https://myshittycode.com/wp-content/uploads/2023/08/gcp-doc-768x210.png 768w, https://myshittycode.com/wp-content/uploads/2023/08/gcp-doc-1536x420.png 1536w, https://myshittycode.com/wp-content/uploads/2023/08/gcp-doc.png 1610w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>To verify this, go to <strong>Security</strong> > <strong>VPC Service Controls</strong> > <strong>MANAGE POLICIES</strong>. </p>



<figure class="wp-block-image aligncenter size-large is-resized"><img decoding="async" src="https://myshittycode.com/wp-content/uploads/2023/08/vpc-sc-manage-policies-1024x219.png?x45560" alt="" class="wp-image-2364" style="width:700px" width="700" srcset="https://myshittycode.com/wp-content/uploads/2023/08/vpc-sc-manage-policies-1024x219.png 1024w, https://myshittycode.com/wp-content/uploads/2023/08/vpc-sc-manage-policies-300x64.png 300w, https://myshittycode.com/wp-content/uploads/2023/08/vpc-sc-manage-policies-768x164.png 768w, https://myshittycode.com/wp-content/uploads/2023/08/vpc-sc-manage-policies.png 1162w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>In this example, the &#8220;main&#8221; access policy is scoped to a project (covered by blue color).</p>



<figure class="wp-block-image aligncenter size-large is-resized"><img decoding="async" src="https://myshittycode.com/wp-content/uploads/2023/08/scoped-policy-1024x390.png?x45560" alt="" class="wp-image-2365" style="width:700px" width="700" srcset="https://myshittycode.com/wp-content/uploads/2023/08/scoped-policy-1024x390.png 1024w, https://myshittycode.com/wp-content/uploads/2023/08/scoped-policy-300x114.png 300w, https://myshittycode.com/wp-content/uploads/2023/08/scoped-policy-768x293.png 768w, https://myshittycode.com/wp-content/uploads/2023/08/scoped-policy.png 1108w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>There are 2 ways to fix this.</p>



<h3 class="wp-block-heading" id="option-a-keep-existing-scoped-access-policy-create-dummy-unscoped-access-policy">Option A: Keep Existing Scoped Access Policy, Create Dummy Unscoped Access Policy</h3>



<p>If you share this GCP org with other team members and you want to get it working without impacting other GCP resources, the easiest way is to create another access policy that is unscoped (i.e., no project or folder specified) at the org level. This unscoped access policy does not have any VPC SC perimeters configured.</p>



<p>In this example, an unscoped access policy named &#8220;default&#8221; is created.</p>



<figure class="wp-block-image aligncenter size-large is-resized"><img decoding="async" src="https://myshittycode.com/wp-content/uploads/2023/08/scoped-unscoped-policies-1024x439.png?x45560" alt="" class="wp-image-2366" style="width:700px" width="700" srcset="https://myshittycode.com/wp-content/uploads/2023/08/scoped-unscoped-policies-1024x439.png 1024w, https://myshittycode.com/wp-content/uploads/2023/08/scoped-unscoped-policies-300x128.png 300w, https://myshittycode.com/wp-content/uploads/2023/08/scoped-unscoped-policies-768x329.png 768w, https://myshittycode.com/wp-content/uploads/2023/08/scoped-unscoped-policies.png 1102w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>Once the changes are propagated, you can execute the same <strong>gsutil</strong> command successfully.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
&gt;  gsutil ls gs://my-shitty-bucket
gs://my-shitty-bucket/my-shitty-file.jpg
</pre></div>


<h3 class="wp-block-heading" id="option-b-preferred-delete-existing-scoped-access-policy-create-unscoped-access-policy-with-vpc-sc-perimeter">Option B (Preferred): Delete Existing Scoped Access Policy, Create Unscoped Access Policy with VPC SC Perimeter</h3>



<p>Unfortunately, an existing scoped access policy cannot be unscoped. So, if you accidentally create a scoped access policy, you can delete it and create an unscoped access policy instead, which requires you to reconfigure the VPC SC perimeter. The upside is you won&#8217;t confuse yourself with multiple access policies if you truly don&#8217;t need the scoped access policy. </p>



<p>In this example, an unscoped access policy named &#8220;default&#8221; is created, and it also has the VPC SC perimeter configured with the same settings.</p>



<figure class="wp-block-image aligncenter size-large is-resized"><img decoding="async" src="https://myshittycode.com/wp-content/uploads/2023/08/unscoped-policy-1024x382.png?x45560" alt="" class="wp-image-2381" style="width:700px" width="700" srcset="https://myshittycode.com/wp-content/uploads/2023/08/unscoped-policy-1024x382.png 1024w, https://myshittycode.com/wp-content/uploads/2023/08/unscoped-policy-300x112.png 300w, https://myshittycode.com/wp-content/uploads/2023/08/unscoped-policy-768x286.png 768w, https://myshittycode.com/wp-content/uploads/2023/08/unscoped-policy.png 1126w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>Once the changes are propagated, the same <strong>gsutil</strong> command will also execute successfully.</p>
<p>The post <a rel="nofollow" href="https://myshittycode.com/2023/08/18/vpc-sc-2-ways-to-fix-no_matching_access_level-error/">VPC SC: 2 Ways to Fix NO_MATCHING_ACCESS_LEVEL Error</a> appeared first on <a rel="nofollow" href="https://myshittycode.com">My Shitty Code</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://myshittycode.com/2023/08/18/vpc-sc-2-ways-to-fix-no_matching_access_level-error/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2359</post-id>	</item>
		<item>
		<title>Vertex AI PaLM: Intro to text-bison</title>
		<link>https://myshittycode.com/2023/08/01/vertex-ai-palm-intro-to-text-bison/</link>
					<comments>https://myshittycode.com/2023/08/01/vertex-ai-palm-intro-to-text-bison/#respond</comments>
		
		<dc:creator><![CDATA[Shitty Author]]></dc:creator>
		<pubDate>Tue, 01 Aug 2023 17:58:06 +0000</pubDate>
				<category><![CDATA[AI]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Generative AI Studio]]></category>
		<category><![CDATA[Google Cloud Platform]]></category>
		<category><![CDATA[PaLM 2]]></category>
		<category><![CDATA[Vertex AI]]></category>
		<guid isPermaLink="false">https://myshittycode.com/?p=2314</guid>

					<description><![CDATA[<p>What is text-bison Google&#8217;s PaLM 2 for text (text-bison) is recently GA&#8217;d. This foundation model is optimized for natural language tasks and it comes in 4 sizes (gecko, otter, bison, and unicorn). To date, unicorn doesn&#8217;t exist yet, no pun intended&#8230; unless one decides to stick an ice cream cone on a pony&#8217;s forehead at [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://myshittycode.com/2023/08/01/vertex-ai-palm-intro-to-text-bison/">Vertex AI PaLM: Intro to text-bison</a> appeared first on <a rel="nofollow" href="https://myshittycode.com">My Shitty Code</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<div class="wp-block-rank-math-toc-block" id="rank-math-toc"><h2>Table of Contents</h2><nav><ul><li><a href="#what-is-text-bison">What is text-bison</a></li><li><a href="#getting-started">Getting Started</a><ul><li><a href="#freeform-form">Freeform Form</a></li><li><a href="#structured-form">Structured Form</a></li><li><a href="#export-code">Export Code</a></li></ul></li></ul></nav></div>



<h2 class="wp-block-heading" id="what-is-text-bison">What is text-bison</h2>



<p>Google&#8217;s PaLM 2 for text (<a href="https://cloud.google.com/vertex-ai/docs/generative-ai/model-reference/text" target="_blank" rel="noopener">text-bison</a>) is recently GA&#8217;d. This foundation model is optimized for natural language tasks and it comes in 4 sizes (gecko, otter, bison, and unicorn). To date, unicorn doesn&#8217;t exist yet, no pun intended&#8230; unless one decides to stick an ice cream cone on a pony&#8217;s forehead at a county fair right now. If you know how to use OpenAI&#8217;s ChatGPT or Google Bard, you already know how to use text-bison.</p>



<h2 class="wp-block-heading" id="getting-started">Getting Started</h2>



<p>The fastest way to explore text-bison is to leverage <a href="https://cloud.google.com/vertex-ai/docs/generative-ai/learn/generative-ai-studio" target="_blank" rel="noopener">Generative AI Studio</a>, select the model to use, and get going with prompt design with absolutely no code. The pricing is listed <a href="https://cloud.google.com/vertex-ai/pricing" target="_blank" rel="noopener">here</a>. For text-bison, you can either use freeform or structured form.</p>



<h3 class="wp-block-heading" id="freeform-form">Freeform Form</h3>



<p>The freeform form is basically a giant text area for you to write anything you want. In this example, I want to put AI to good use&#8230; by analyzing one of Bruno Mars&#8217; lyrics.</p>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe loading="lazy" title="Bruno Mars - When I Was Your Man (Official Music Video)" width="500" height="281" src="https://www.youtube.com/embed/ekzHIouo8Q4?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>



<p>By providing concise instructions and the lyric snippet, the AI model accurately describes what Bruno&#8217;s trying to tell us, how he feels, and ways for him to improve his personal relationship.</p>



<figure class="wp-block-image aligncenter size-large is-resized"><img loading="lazy" decoding="async" src="https://myshittycode.com/wp-content/uploads/2023/08/text-bison-freeform-1024x586.png?x45560" alt="" class="wp-image-2316" width="1024" height="586" srcset="https://myshittycode.com/wp-content/uploads/2023/08/text-bison-freeform-1024x586.png 1024w, https://myshittycode.com/wp-content/uploads/2023/08/text-bison-freeform-300x172.png 300w, https://myshittycode.com/wp-content/uploads/2023/08/text-bison-freeform-768x440.png 768w, https://myshittycode.com/wp-content/uploads/2023/08/text-bison-freeform-1536x879.png 1536w, https://myshittycode.com/wp-content/uploads/2023/08/text-bison-freeform-2048x1172.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<h3 class="wp-block-heading" id="structured-form">Structured Form</h3>



<p>The structured form leverages the few-shot prompt technique to assist the model to provide a more specific response. In this case, you provide some context and a few examples of how the model should respond. Then, you test it by providing an input for the model to generate an output.</p>



<figure class="wp-block-image aligncenter size-large is-resized"><img loading="lazy" decoding="async" src="https://myshittycode.com/wp-content/uploads/2023/08/text-bison-structured-1024x629.png?x45560" alt="" class="wp-image-2317" width="1024" height="629" srcset="https://myshittycode.com/wp-content/uploads/2023/08/text-bison-structured-1024x629.png 1024w, https://myshittycode.com/wp-content/uploads/2023/08/text-bison-structured-300x184.png 300w, https://myshittycode.com/wp-content/uploads/2023/08/text-bison-structured-768x471.png 768w, https://myshittycode.com/wp-content/uploads/2023/08/text-bison-structured-1536x943.png 1536w, https://myshittycode.com/wp-content/uploads/2023/08/text-bison-structured-2048x1257.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<h3 class="wp-block-heading" id="export-code">Export Code</h3>



<p>In either freeform or structured form, once you are pleased with your designed prompt, you can export it to code by clicking on the <strong>&lt;&gt; VIEW CODE</strong> link on the top right. </p>



<figure class="wp-block-image aligncenter size-large is-resized"><img loading="lazy" decoding="async" src="https://myshittycode.com/wp-content/uploads/2023/08/text-bison-code-1-1024x970.png?x45560" alt="" class="wp-image-2327" width="768" height="728" srcset="https://myshittycode.com/wp-content/uploads/2023/08/text-bison-code-1-1024x970.png 1024w, https://myshittycode.com/wp-content/uploads/2023/08/text-bison-code-1-300x284.png 300w, https://myshittycode.com/wp-content/uploads/2023/08/text-bison-code-1-768x728.png 768w, https://myshittycode.com/wp-content/uploads/2023/08/text-bison-code-1-1536x1456.png 1536w, https://myshittycode.com/wp-content/uploads/2023/08/text-bison-code-1.png 1566w" sizes="auto, (max-width: 768px) 100vw, 768px" /></figure>
<p>The post <a rel="nofollow" href="https://myshittycode.com/2023/08/01/vertex-ai-palm-intro-to-text-bison/">Vertex AI PaLM: Intro to text-bison</a> appeared first on <a rel="nofollow" href="https://myshittycode.com">My Shitty Code</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://myshittycode.com/2023/08/01/vertex-ai-palm-intro-to-text-bison/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2314</post-id>	</item>
	</channel>
</rss>

<!--
Performance optimized by W3 Total Cache. Learn more: https://www.boldgrid.com/w3-total-cache/?utm_source=w3tc&utm_medium=footer_comment&utm_campaign=free_plugin

Page Caching using Disk: Enhanced 
Lazy Loading (feed)
Database Caching using Disk

Served from: myshittycode.com @ 2026-02-19 15:14:52 by W3 Total Cache
-->