From e913344850f6b8b28b1d5f36557cfc1df9f1e2e7 Mon Sep 17 00:00:00 2001 From: Alexander Clouter Date: Mon, 19 Apr 2021 08:23:54 +0100 Subject: [PATCH] [WIP] deploy to GCP --- contrib/gcp/.gitignore | 1 + contrib/gcp/README.md | 153 ++++++++++++++ contrib/gcp/portier.jinja | 328 +++++++++++++++++++++++++++++++ contrib/gcp/portier.jinja.schema | 122 ++++++++++++ contrib/gcp/portier.yaml.dist | 15 ++ 5 files changed, 619 insertions(+) create mode 100644 contrib/gcp/.gitignore create mode 100644 contrib/gcp/README.md create mode 100644 contrib/gcp/portier.jinja create mode 100644 contrib/gcp/portier.jinja.schema create mode 100644 contrib/gcp/portier.yaml.dist diff --git a/contrib/gcp/.gitignore b/contrib/gcp/.gitignore new file mode 100644 index 00000000..772ca2e4 --- /dev/null +++ b/contrib/gcp/.gitignore @@ -0,0 +1 @@ +portier.yaml diff --git a/contrib/gcp/README.md b/contrib/gcp/README.md new file mode 100644 index 00000000..c3dc0055 --- /dev/null +++ b/contrib/gcp/README.md @@ -0,0 +1,153 @@ +Portier Deployment to Google Cloud Platform (GCP). + +The deployment fronts Portier with Redis running under [Cloud Run](https://cloud.google.com/run) with an [external cross-region global load balancer](https://cloud.google.com/load-balancing/docs/https#cross-region_load_balancing) providing [resilience to region failure](https://cloud.google.com/run/docs/multiple-regions) (though only a single region is used). + +Baseline costs are ~$80/month when idle: + + * [Cloud Run](https://cloud.google.com/run/pricing#tables) (~$10/month) + * You may wish to pick a Tier 1 region for better pricing where possible + * [Redis](https://cloud.google.com/memorystore/docs/redis/pricing#instance_pricing) (~$50/month) + * Uses standard HA tier with 1GiB capacity + * [Load Balancer](https://cloud.google.com/vpc/network-pricing#lb) (~$20/month) + * Deployment fits within the first five forwarding rules pricing + +## Related Links + + * [Deployment Manager](https://cloud.google.com/deployment-manager) + * [Jinja Template Documentation](https://jinja.palletsprojects.com/en/2.11.x/templates/) + +## Outstanding Issues + + * only a single region as GCP's Redis HA deployment only operates within a single region and we have to use the same instance everywhere as otherwise the server 'client' could hit a different backend to the browser 'client' + * The [type providers](https://cloud.google.com/deployment-manager/docs/configuration/type-providers/advanced-configuration-options) used need massaging to allow updates + * Hard coding of the Redis port to `6379/tcp` + * workaround: `Reference [$(ref.portier-europe-west4-redis.port)], was not of type string but [NUMBER], cannot replace inside ["redis://:abcd@192.0.2.1:$($(ref.portier-europe-west4-redis.port))/0\n"]` + * GCP's Deployment Manager is mostly awful, so when GCP throws you lemons, it provides zero tools (or documentation) to make lemonade + * there is no cast operator available that works on `$(ref ...)` + * we cannot use [`outputs`](https://cloud.google.com/deployment-manager/docs/configuration/expose-information-outputs) as it uses pass by reference and creates the same problem + * [using Python to build the YAML configuration](https://cloud.google.com/deployment-manager/docs/configuration/templates/create-basic-template#python) to work around this seems to be a little excessive + * support for [in-transit encryption](https://cloud.google.com/memorystore/docs/redis/in-transit-encryption) + * [redis crate supports it](https://docs.rs/redis/0.20.0/redis/enum.ConnectionAddr.html#variant.TcpTls) though [Portier's `pubsub.rs` explicitly does not](https://github.com/portier/portier-broker/issues/351) + * we would need to be able to set a [custom private CA](https://cloud.google.com/memorystore/docs/redis/in-transit-encryption#certificate_authority) for these connections + * could use an SSL sidecar such as [`socat`](http://www.dest-unreach.org/socat/)/[`stunnel`](https://www.stunnel.org/) (and no `LD_PRELOAD` hack for SSL clients exist) but container users tend to subscribe to various purity laws that frown upon running supervisors whilst ignoring the very real world problems it solves + * not a huge problem as the expected deployment is that this will be the sole service running in a GCP project so nothing would be around to sniff the wire traffic even if it could + * `smtp_password` and the Redis connection URL are not stored in [Google Key Manager Service](https://cloud.google.com/kms) + +# Preflight + +You will need to already have have a GCP account, created a project with an billing account assigned to it and that you have at least 'Editor' permissions on it. + + gcloud --project [PROJECT_ID] services enable \ + cloudbuild.googleapis.com \ + cloudresourcemanager.googleapis.com \ + containerregistry.googleapis.com \ + deploymentmanager.googleapis.com \ + redis.googleapis.com \ + run.googleapis.com \ + sourcerepo.googleapis.com \ + vpcaccess.googleapis.com + +Where `[PROJECT_ID]` is the GCP project name you want to deploy to. + +Obtain the `[PROJECT_NUMBER]` which is the `projectNumber` output from running: + + gcloud projects describe [PROJECT_ID] + +Now elevate the permissions of the deployment manager account using: + + gcloud projects add-iam-policy-binding [PROJECT_ID] --member serviceAccount:[PROJECT_NUMBER]@cloudservices.gserviceaccount.com --role roles/resourcemanager.projectIamAdmin + gcloud projects add-iam-policy-binding [PROJECT_ID] --member serviceAccount:[PROJECT_NUMBER]@cloudservices.gserviceaccount.com --role roles/source.admin + gcloud projects add-iam-policy-binding [PROJECT_ID] --member serviceAccount:[PROJECT_NUMBER]@cloudservices.gserviceaccount.com --role roles/run.admin + +Create a GCP Deployment Manager configuration file to describe the deployment: + + cp contrib/gcp/portier.yaml.dist contrib/gcp/portier.yaml + +Edit `contrib/gcp/portier.yaml` to reflect the desired deployment as detailed in [`portier.jinja.schema`](./portier.jinja.schema); most of which just populates the variables described in [`config.toml`](../../config.toml.dist). + +**N.B.** once deployed you must not change the *ordering* of `regions` as it is used to select IP ranges that once set are immutable, if you need to disable a region update the entry to include the string 'ignore' which is case insensitively matched on by the deployment template + +If you used `data_url` in `portier.yaml` you will need to run something like the following (matching your `data_url` to the uploaded name): + + gsutil mb -p kx-portier -l EU gs://[PROJECT_ID] + tar --exclude '*.po' -vzcf data.tar.gz lang res tmpl + gsutil cp -a public-read data.tar.gz gs://[PROJECT_ID]/data-$(cat /proc/sys/kernel/random/uuid).tar.gz + +Preview the deployment by running: + + gcloud --project [PROJECT_ID] deployment-manager deployments create [DEPLOYMENT] --config contrib/gcp/portier.yaml --preview + +Where `[DEPLOYMENT]` is what you want to name the deployment (recommended you use `portier`). + +If you are happy with the proposed deployment, then run: + + gcloud --project [PROJECT_ID] deployment-manager deployments cancel-preview [DEPLOYMENT] + gcloud --project [PROJECT_ID] deployment-manager deployments update [DEPLOYMENT] --config contrib/gcp/portier.yaml + git config credential.'https://source.developers.google.com'.helper gcloud.sh + git remote add google https://source.developers.google.com/p/[PROJECT_ID]/r/[DEPLOYMENT] + +Obtain the IPv4 and IPv6 addresses used and set the A and AAAA DNS RR for `hostname` you provided in `contrib/gcp/portier.yaml`: + + gcloud --project [PROJECT_ID] compute addresses list + +Once done, the SSL certificate for the service should be automatically generated at some stage. + +Lastly you need to follow the [Portier deploy instructions below](#portier) and afterwards you should be operational. + +# Deploy + +## Portier + +If you want to deploy a new version of Portier, just update your local repository and run: + + git tag --force prod + git push --force --all google + git push --force --tags google + +This will kick off a new [build you can monitor](https://console.cloud.google.com/cloud-build/dashboard) using: + + gcloud --project [PROJECT_ID] builds list + +After about twenty minutes you should have a new image built ready for use and once complete you will need to run: + + gcloud --project [PROJECT_ID] run services update [DEPLOYMENT] --region [REGION] --image gcr.io/[PROJECT_ID]/[DEPLOYMENT]:prod + +### Data Directory + +If you are just looking to update the data directory (which you should do each time you update Portier) use: + + tar --exclude '*.po' -vzcf data.tar.gz lang res tmpl + gsutil cp -a public-read data.tar.gz gs://[PROJECT_ID]/data-[UUID].tar.gz + +Then kick off a new build manually with: + + gcloud --project [PROJECT_ID] beta builds triggers run portier --tag=prod + +## Deployment Manager + +To update the deployment, run: + + gcloud --project [PROJECT_ID] deployment-manager deployments update [DEPLOYMENT] --config contrib/gcp/portier.yaml + +### Remove + + gcloud --project [PROJECT_ID] deployment-manager deployments delete [DEPLOYMENT] + +#### Abandon + +This process describes how to remove the deployment whilst retaining the IPs and certificate resources, ready for you to be able to redeploy without error. + + gcloud --project [PROJECT_ID] deployment-manager deployments delete [DEPLOYMENT] --delete-policy=abandon + gcloud --project [PROJECT_ID] compute forwarding-rules delete [DEPLOYMENT]-globalforwardingrule-ipv4 --global + gcloud --project [PROJECT_ID] compute forwarding-rules delete [DEPLOYMENT]-globalforwardingrule-ipv6 --global + gcloud --project [PROJECT_ID] compute target-https-proxies delete [DEPLOYMENT]-targethttpsproxy + gcloud --project [PROJECT_ID] compute url-maps delete [DEPLOYMENT]-urlmap + gcloud --project [PROJECT_ID] compute backend-services delete [DEPLOYMENT]-backendservice --global + gcloud --project [PROJECT_ID] compute network-endpoint-groups delete [DEPLOYMENT] --region europe-west4 + gcloud --project [PROJECT_ID] run services delete --platform managed [DEPLOYMENT] --region europe-west4 + gcloud --project [PROJECT_ID] compute networks vpc-access connectors delete [DEPLOYMENT] --region europe-west4 + #gcloud --project [PROJECT_ID] redis instances delete [DEPLOYMENT] --region europe-west4 + gcloud --project [PROJECT_ID] beta builds triggers delete [DEPLOYMENT] + #gcloud --project [PROJECT_ID] source repos delete [DEPLOYMENT] + +**N.B.** you do not need to delete Redis or source repository, but the commands are shown for completeness diff --git a/contrib/gcp/portier.jinja b/contrib/gcp/portier.jinja new file mode 100644 index 00000000..f69f8840 --- /dev/null +++ b/contrib/gcp/portier.jinja @@ -0,0 +1,328 @@ +resources: + +- name: {{ env["deployment"] }}-typeprovider-sourcerepo + type: deploymentmanager.v2beta.typeProvider + properties: + descriptorUrl: https://sourcerepo.googleapis.com/$discovery/rest?version=v1 + options: + inputMappings: + - fieldName: Authorization + location: HEADER + value: > + $.concat("Bearer ", $.googleOauth2AccessToken()) + +- name: {{ env["deployment"] }}-typeprovider-cloudbuild + type: deploymentmanager.v2beta.typeProvider + properties: + descriptorUrl: https://cloudbuild.googleapis.com/$discovery/rest?version=v1 + options: + inputMappings: + - fieldName: Authorization + location: HEADER + value: > + $.concat("Bearer ", $.googleOauth2AccessToken()) + +{# https://gist.github.com/dinvlad/fcf72039c403bc2bf46663fb43c62a57 #} +- name: {{ env["deployment"] }}-typeprovider-run + type: deploymentmanager.v2beta.typeProvider + properties: + descriptorUrl: https://run.googleapis.com/$discovery/rest?version=v1 + options: + inputMappings: + - fieldName: Authorization + location: HEADER + value: > + $.concat("Bearer ", $.googleOauth2AccessToken()) + +{# https://stackoverflow.com/questions/66429971/how-to-create-a-network-endpoint-group-via-gcp-deployment-manager #} +- name: {{ env["deployment"] }}-typeprovider-nsg + type: deploymentmanager.v2beta.typeProvider + properties: + descriptorUrl: https://www.googleapis.com/discovery/v1/apis/compute/v1/rest + options: + inputMappings: + - fieldName: Authorization + location: HEADER + value: > + $.concat("Bearer ", $.googleOauth2AccessToken()) + +- name: {{ env["deployment"] }}-typeprovider-vpcaccess + type: deploymentmanager.v2beta.typeProvider + properties: + descriptorUrl: https://vpcaccess.googleapis.com/$discovery/rest?version=v1 + options: + inputMappings: + - fieldName: Authorization + location: HEADER + value: > + $.concat("Bearer ", $.googleOauth2AccessToken()) + +- name: {{ env["deployment"] }}-sourcerepo + type: {{ env["project"] }}/{{ env["deployment"] }}-typeprovider-sourcerepo:projects.repos + metadata: + dependsOn: + - {{ env["deployment"] }}-typeprovider-sourcerepo + properties: + parent: projects/{{ env["project"] }} + name: projects/{{ env["project"] }}/repos/{{ env["deployment"] }} + +- name: {{ env["deployment"] }}-cloudbuild-trigger + type: {{ env["project"] }}/{{ env["deployment"] }}-typeprovider-cloudbuild:projects.triggers + metadata: + dependsOn: + - {{ env["deployment"] }}-typeprovider-cloudbuild + - {{ env["deployment"] }}-sourcerepo + properties: + projectId: {{ env["project"] }} + name: {{ env["deployment"] }} + triggerTemplate: + projectId: {{ env["project"] }} + repoName: {{ env["deployment"] }} + tagName: ^prod$ + build: + images: + - gcr.io/$PROJECT_ID/$REPO_NAME:$TAG_NAME + steps: + - name: gcr.io/cloud-builders/docker + args: + - build + - -t + - gcr.io/$PROJECT_ID/$REPO_NAME:$TAG_NAME +{%- if "data_url" in properties %} + - --build-arg=data_url={{ properties["data_url"] }} +{%- endif %} + - . + timeout: 3600s + +- name: {{ env['deployment'] }}-serviceaccount + type: iam.v1.serviceAccount + properties: + accountId: {{ env['deployment'] }} + +- name: {{ env['deployment'] }}-serviceaccount-logWriter + type: gcp-types/cloudresourcemanager-v1:virtual.projects.iamMemberBinding + properties: + resource: {{ env["project"] }} + role: roles/logging.logWriter + member: serviceAccount:$(ref.{{ env["deployment"] }}-serviceaccount.email) + +- name: {{ env['deployment'] }}-serviceaccount-traceAgent + type: gcp-types/cloudresourcemanager-v1:virtual.projects.iamMemberBinding + properties: + resource: {{ env["project"] }} + role: roles/cloudtrace.agent + member: serviceAccount:$(ref.{{ env["deployment"] }}-serviceaccount.email) + +- name: {{ env["deployment"] }}-redis + type: gcp-types/redis-v1:projects.locations.instances + properties: + parent: projects/{{ env["project"] }}/locations/{{ properties["region"] }} + instanceId: {{ env["deployment"] }} + tier: STANDARD_HA + redisVersion: REDIS_5_0 + memorySizeGb: 1 + authEnabled: true + +- name: {{ env["deployment"] }}-redis-authstring + type: gcp-types/redis-v1:redis.projects.locations.instances.getAuthString + properties: + name: $(ref.{{ env["deployment"] }}-redis.name) + +- name: {{ env["deployment"] }}-connector + type: {{ env["project"] }}/{{ env["deployment"] }}-typeprovider-vpcaccess:projects.locations.connectors + metadata: + dependsOn: + - {{ env["deployment"] }}-typeprovider-vpcaccess + properties: + parent: projects/{{ env["project"] }}/locations/{{ properties["region"] }} + network: default + connectorId: {{ env["deployment"] }} + ipCidrRange: 10.8.0.0/28 + minThroughput: 200 + maxThroughput: 300 + +- name: {{ env["deployment"] }}-run + type: {{ env["project"] }}/{{ env["deployment"] }}-typeprovider-run:projects.locations.services + metadata: + dependsOn: + - {{ env["deployment"] }}-typeprovider-run + properties: + parent: projects/{{ env["project"] }}/locations/{{ properties["region"] }} + kind: Service + apiVersion: serving.knative.dev/v1 + metadata: + namespace: {{ env["project"] }} + name: {{ env["deployment"] }} + annotations: + run.googleapis.com/ingress: internal-and-cloud-load-balancing + run.googleapis.com/ingress-status: internal-and-cloud-load-balancing + spec: + template: + metadata: + name: {{ env["deployment"] }}-0000 + annotations: + run.googleapis.com/vpc-access-egress: private-ranges-only + run.googleapis.com/vpc-access-connector: $(ref.{{ env["deployment"] }}-connector.name) + autoscaling.knative.dev/minScale: '{{ properties["instances_min"] }}' + autoscaling.knative.dev/maxScale: '{{ properties["instances_max"] }}' + spec: + serviceAccountName: $(ref.{{ env["deployment"] }}-serviceaccount.email) + timeoutSeconds: 30 + containers: + - image: gcr.io/{{ env["project"] }}/{{ env["deployment"] }}:prod + ports: + - name: http1 + containerPort: 3333 + env: + - name: BROKER_PUBLIC_URL + value: https://{{ properties["hostname"] }} +{%- if "allowed_origins" in properties %} + - name: BROKER_ALLOWED_ORIGINS + value: {{ properties["allowed_origins"]|join(',') }} +{%- elif "allowed_origins_file" in properties %} + - name: BROKER_ALLOWED_ORIGINS + value: "@/opt/portier-broker/{{ properties["allowed_origins_file"] }}" +{%- endif %} +{%- if "allowed_domains" in properties %} + - name: BROKER_ALLOWED_DOMAINS + value: {{ properties["allowed_domains"]|join(',') }} +{%- elif "allowed_domains_file" in properties %} + - name: BROKER_ALLOWED_DOMAINS + value: "@/opt/portier-broker/{{ properties["allowed_domains_file"] }}" +{%- endif %} +{%- if "blocked_domains" in properties %} + - name: BROKER_BLOCKED_DOMAINS + value: {{ properties["blocked_domains"]|join(',') }} +{%- elif "blocked_domains_file" in properties %} + - name: BROKER_BLOCKED_DOMAINS + value: "@/opt/portier-broker/{{ properties["blocked_domains_file"] }}" +{%- endif %} + - name: BROKER_TRUSTED_PROXIES +{# https://cloud.google.com/load-balancing/docs/https#source_ip_addresses_for_client_packets #} +{% set trusted_proxies = [ "35.191.0.0/16", "130.211.0.0/22" ] %} +{% for version in [ 4, 6 ] %} +{% set trusted_proxies = trusted_proxies.append("$(ref." ~ env["deployment"] ~ "-globaladdress-ipv" ~ version ~ ".address)") %} +{% endfor %} + value: {{ trusted_proxies|join(',') }} + - name: BROKER_REDIS_URL + {# hardcoded port, see issue details in README #} + value: redis://:$(ref.{{ env["deployment"] }}-redis-authstring.authString)@$(ref.{{ env["deployment"] }}-redis.host):6379/0 + - name: BROKER_FROM_NAME + value: {{ properties["from_name"] }} + - name: BROKER_FROM_ADDRESS + value: {{ properties["from_address"] }} + - name: BROKER_SMTP_SERVER + value: {{ properties["smtp_hostname"] }}:{{ properties["smtp_port"] }} + - name: BROKER_SMTP_USERNAME + value: {{ properties["smtp_username"] }} + - name: BROKER_SMTP_PASSWORD + value: {{ properties["smtp_password"] }} +{%- if "resolver" in properties %} + - name: BROKER_VERIFY_WITH_RESOLVER + value: {{ properties["resolver"] }} + - name: BROKER_VERIFY_PUBLIC_IP + value: "true" +{%- endif %} + resources: + limits: + cpu: 1000m + memory: 128Mi + +- name: {{ env["deployment"] }}-run-iam + type: {{ env["project"] }}/{{ env["deployment"] }}-typeprovider-run:run.projects.locations.services.setIamPolicy + metadata: + dependsOn: + - {{ env["deployment"] }}-typeprovider-run + - {{ env["deployment"] }}-run + properties: + resource: projects/{{ env["project"] }}/locations/{{ properties["region"] }}/services/{{ env["deployment"] }} + policy: + bindings: + - members: + - allUsers + role: roles/run.invoker + +- name: {{ env["deployment"] }}-nsg + type: {{ env["project"] }}/{{ env["deployment"] }}-typeprovider-nsg:regionNetworkEndpointGroups + metadata: + dependsOn: + - {{ env["deployment"] }}-typeprovider-nsg + properties: + project: {{ env["project"] }} + region: {{ properties["region"] }} + name: {{ env["deployment"] }} + networkEndpointType: SERVERLESS + cloudRun: + service: $(ref.{{ env["deployment"] }}-run.metadata.name) + +- name: {{ env["deployment"] }}-backendservice + type: compute.v1.backendService + properties: + backends: + - group: $(ref.{{ env["deployment"] }}-nsg.selfLink) + +- name: {{ env["deployment"] }}-urlmap + type: compute.v1.urlMap + properties: + # redirect to mitigate against skiddies burning a hole in your bank account + defaultUrlRedirect: + hostRedirect: {{ properties["website_hostname"] }} + httpsRedirect: true + pathRedirect: {{ properties["website_path"] }} + redirectResponseCode: SEE_OTHER + stripQuery: true + hostRules: + - hosts: + - {{ properties["hostname"] }} + pathMatcher: main + pathMatchers: + - name: main + defaultUrlRedirect: + hostRedirect: {{ properties["website_hostname"] }} + httpsRedirect: true + pathRedirect: {{ properties["website_path"] }} + redirectResponseCode: SEE_OTHER + stripQuery: true + # portier-broker:src/router.rs (do not include the misc paths) + pathRules: + - paths: + - /.well-known/openid-configuration + - /keys.json + - /auth + - /normalize + - /token + - /callback + - /confirm + - /static/* + service: $(ref.{{ env["deployment"] }}-backendservice.selfLink) + +- name: {{ env["deployment"] }}-sslcertificate + type: compute.v1.sslCertificate + properties: + type: MANAGED + managed: + domains: + - {{ properties["hostname"] }} + +- name: {{ env["deployment"] }}-targethttpsproxy + type: compute.v1.targetHttpsProxy + properties: + urlMap: $(ref.{{ env["deployment"] }}-urlmap.selfLink) + sslCertificates: + - $(ref.{{ env["deployment"] }}-sslcertificate.selfLink) + +{% for version in [ 4, 6 ] %} +- name: {{ env["deployment"] }}-globaladdress-ipv{{ version }} + type: compute.v1.globalAddress + properties: + networkTier: PREMIUM + ipVersion: IPV{{ version }} + +- name: {{ env["deployment"] }}-globalforwardingrule-ipv{{ version }} + type: compute.v1.globalForwardingRule + properties: + loadBalancingScheme: EXTERNAL + IPAddress: $(ref.{{ env["deployment"] }}-globaladdress-ipv{{ version }}.address) + portRange: 443-443 + target: $(ref.{{ env["deployment"] }}-targethttpsproxy.selfLink) +{% endfor %} diff --git a/contrib/gcp/portier.jinja.schema b/contrib/gcp/portier.jinja.schema new file mode 100644 index 00000000..6ee7d902 --- /dev/null +++ b/contrib/gcp/portier.jinja.schema @@ -0,0 +1,122 @@ +info: + title: Portier Broker Service + author: https://github.com/portier + +required: +- region +- hostname +- website_hostname +- from_address +- smtp_hostname +- smtp_username +- smtp_password + +properties: + region: + type: string + description: > + Region (https://cloud.google.com/run/docs/locations) to deploy the service to. + + hostname: + type: string + description: > + Constructs a value for config.toml:public_url using the template 'http://[hostname]' + + website_hostname: + type: string + description: > + Organisation website hostname we redirect unknown requests to + + website_path: + type: string + description: > + Organisation website path we redirect unknown requests to + default: / + + data_url: + type: string + description: > + URL to .tar.gz to provide custom {lang,res,tmpl} contents, see Dockerfile for details. + This is publically accessible over HTTP so avoid including sensitive data in it and/or use a UUID in the path of the URL. + + allowed_origins: + type: array + description: > + Used to construct config.toml:allowed_origins + + allowed_origins_file: + type: string + description: > + Used to construct config.toml:allowed_origins (value is prepended with "@/opt/portier-broker/") + + allowed_domains: + type: array + description: > + Used to construct config.toml:allowed_domains + + allowed_domains_file: + type: string + description: > + Used to construct config.toml:allowed_domains (value is prepended with "@/opt/portier-broker/") + + blocked_domains: + type: array + description: > + Used to construct config.toml:blocked_domains + + blocked_domains_file: + type: string + description: > + Used to construct config.toml:blocked_domains (value is prepended with "@/opt/portier-broker/") + + resolver: + type: string + description: > + Used to populate config.toml:verify_with_resolver (also sets verify_public_ip to true) + default: 169.254.169.254:53 + + from_name: + type: string + description: > + Used to populate config.toml:from_name + default: Portier + + from_address: + type: string + description: > + Used to populate config.toml:from_address (eg. 'noreply@example.com') + + smtp_hostname: + type: string + description: > + Hostname for SMTP server + + smtp_port: + type: integer + description: > + Port for SMTP server + default: 25 + + smtp_username: + type: string + description: > + Username for SMTP server + + smtp_password: + type: string + description: > + Password for SMTP server + + instances_min: + type: integer + description: > + Minimum number of instances to retain whilst idle. Recommended one (1) is used + as it will hide the cold-start latency but comes at a cost hence why the default + is set to zero (0) + default: 0 + + instances_max: + type: integer + description: > + Maximum number of instances to run + default: 10 diff --git a/contrib/gcp/portier.yaml.dist b/contrib/gcp/portier.yaml.dist new file mode 100644 index 00000000..5e40fc03 --- /dev/null +++ b/contrib/gcp/portier.yaml.dist @@ -0,0 +1,15 @@ +imports: +- path: portier.jinja + +resources: +- name: portier + type: portier.jinja + properties: + region: europe-west4 + hostname: auth.example.com + website_hostname: example.com + from_address: noreply@example.com + smtp_hostname: smtp.sendgrid.net + smtp_port: 587 + smtp_username: apikey + smtp_password: SG.1234abcd...