Solid State Deploy
Deploy simple websites with Google Cloud and Cloudflare. It is like Netlify with:
- Better performance. Cloudflare has more features for fast websites than Netlify CDN. For instance, HTTP/3 and TLS 1.3 0-RTT.
- Flexibility. You can have crontab jobs and simple scripts (without persistence storage). You will have powerful and well documented Nginx config to define custom headers and redirects.
- Lack of vendor lock-in. We use industry standards like Docker and Nginx. You can change CI, CDN, or Docker cloud separately.
- Local tests. You can run a server on your laptop to test redirects and scripts.
You will have built-in HTTPS and deploy by git push
.
We also have trade-offs. It is not free, but for a simple website, it will cost you cents per month. You need more steps to install it, but after you have the same simple workflow.
Install
-
Create an account in Google Cloud.
-
Go to IAM & Admin → Service Accounts, click Create Service Account and fill form:
- Service Account Name:
Github-actions
- Service Account Description:
Deploy from Github Actions
- Service Account Name:
-
Add Cloud Run Admin, Storage Admin, Service Account User roles.
-
Click Create Key, choose JSON → Create, download and keep file for a while.
-
Open Container Registry and enable the service.
-
Open Cloud Run and start the service.
-
Go to your Github page of your project at Settings → Secrets.
-
Add new secret
WEBSITE_URL
with URL to your website domain (likeexample.com
). -
Add new secret
GCLOUD_PROJECT
with Google Cloud project name liketest-255417
. You can find project ID by opening a project switcher at the top of Google Cloud. -
Choose application name (like
examplecom
) and addGCLOUD_APP
secret with this name. -
Call
base64 key-partition-….json
(file from step 4) and addGCLOUD_AUTH
secret with the base64 content of this file. -
Install Solid State Deploy to your project.
npm i ssdeploy
-
Create Github Actions workflow by calling:
npx ssdeploy init
-
Your project should build HTML files by
npm build
and put them todist/
. -
Push the project’s changes to Github Actions to start deploying. Open Actions tab on Github to check out the process.
-
Go to Cloud Run at Google Cloud and find your server. Open it by clicking on the name and find the URL like
examplecom-hjv54hv.a.run.app
. Check that the website is working. -
Click on Manage Custom Domains → Add mapping. Select your app, Verify a new domain, and enter your domain name. Finish domain verification with Webmaster Central.
-
After verification open Add mapping dialog again, select your app, domain, and leave subdomain blank. You will get
A
andAAAA
records. -
Create a new Cloudflare account. Create a site with
A
andAAAA
records from Cloud Run. -
Enable HTTP/3 and 0-RTT in Cloudflare Network settings.
-
Find Zone ID at site overview and create API token with
cache cleaner
name andCache Purge
/Edit
permission. -
Use them in
CLOUDFLARE_ZONE
andCLOUDFLARE_TOKEN
secrets at Github. -
Go to Google Cloud Run, Manage Custom Domains → Add mapping to add
www
subdomain and addCNAME
record to Cloudflare DNS settings.
We recommend checking the final result for blocking in Russia and recreate Cloudflare account to change IP addressed.
Few extra steps will improve security:
-
Go to Cloudflare SSL/TLS settings and enable Full encryption mode.
-
Add
CAA
records to Cloudflare DNS settings:CAA @ 0 "only allow specific hostname" digicert.com CAA @ 0 "only allow specific hostname" letsencrypt.org CAA www 0 "only allow specific hostname" digicert.com CAA www 0 "only allow specific hostname" letsencrypt.org
-
Enable DNSSEC in DNS settings.
-
Enable HTST by creating
nginx.conf
in the root of your project with:add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"; add_header X-Content-Type-Options "nosniff";
Deploy
Just push commits to master
:
git push origin master
You can switch deploy branch at .Github/workflows/deploy.yml
.
Run Server Locally
To test the Docker image locally run:
npm build
npx ssdeploy run
Deploy Server Locally
You can deploy a server from the laptop. It can be useful to debug.
You need to install Google Cloud SDK and call:
npx ssdeploy deploy
Custom Nginx config
In custom Nginx config, you can define headers and redirects. Create nginx.conf
in your project root.
if ($host ~ ^www\.(?<domain>.+)$) {
return 301 https://$domain$request_uri;
}
location ~* "(\.css|\.png|\.svg|\.woff2)$" {
add_header Cache-Control "public, max-age=31536000, immutable";
}
It will be included inside the server
context.
Custom Docker config
Custom Dockerfile
should be placed at your project root. It can be used
to define crontab jobs:
FROM nginx:alpine
RUN rm -R /etc/nginx/conf.d
COPY ./dist/ /var/www/
COPY ./node_modules/ssdeploy/configs/nginx.conf /etc/nginx/nginx.template
COPY ./nginx.conf /etc/nginx/server.conf
RUN echo "#\!/bin/sh\necho 1" > /etc/periodic/hourly/example
RUN chmod a+x /etc/periodic/hourly/example
CMD crond && envsubst \$PORT < /etc/nginx/nginx.template > /etc/nginx/nginx.conf && nginx