Installing on Google Cloud
On Google Cloud, Tricryption runs as the Ubuntu packages on a Compute Engine VM, with its key database on Cloud SQL for PostgreSQL. Nothing about the product changes: the same packages are installed and the same two provisioning tools run on the VM. What is Google Cloud's is the network, the database instance and how you reach the machine.
The key server is provisioned against the Cloud SQL instance from the start: the instance, its database and its role exist before anything is installed on the VM.
The shape
| Part | How it is set up |
|---|---|
| VM | Compute Engine e2-standard-4 (4 vCPU, 16 GB) on Canonical's Ubuntu 24.04 image (family ubuntu-2404-lts-amd64), with no external address, Shielded VM, OS Login, and no service account. The key server, the Console and the Gateway run on it, each on loopback. |
| Key database | Cloud SQL for PostgreSQL 16, Enterprise edition, db-custom-2-8192 (2 vCPU, 8 GB), zonal, in the VM's zone. Private IP only, reached through private services access on the VM's network. The server requires TLS, and its certificate is issued by Google's managed CA to the instance's DNS name. The key server, the Console and the Gateway connect with sslmode=verify-full against that CA and that name. |
| Administration | IAP TCP forwarding only: the one firewall rule admits tcp:22 from Google's IAP forwarding range, nothing else. The application ports are reached as ssh forwards through that tunnel. |
| Outbound | Cloud NAT on the VM's subnet, for package downloads. |
What you need
- A Google Cloud project with the Compute Engine, IAP, Service Networking and Cloud SQL Admin APIs enabled, and your own sign-in with rights to create those resources.
- A VPC with one subnet in the region, Cloud NAT on it, and the IAP firewall rule above.
- The release's four
.debpackages. See What a release contains. - The release signer's certificate, CA certificate and CRL, to register the release with the key server.
1. Create the database
Allocate a range for private services access on your network and connect it, once per network:
gcloud compute addresses create <range-name> --global --purpose=VPC_PEERING --prefix-length=24 --network=<vpc>
gcloud services vpc-peerings connect --service=servicenetworking.googleapis.com --ranges=<range-name> --network=<vpc>
Create the instance in the VM's zone, with a private address only, TLS required by the server, and the server certificate issued to the instance's DNS name:
gcloud sql instances create <instance> --zone=<zone> --database-version=POSTGRES_16 --tier=db-custom-2-8192 --edition=ENTERPRISE --availability-type=ZONAL --storage-type=SSD --storage-size=20 --network=projects/<project>/global/networks/<vpc> --no-assign-ip --ssl-mode=ENCRYPTED_ONLY --server-ca-mode=GOOGLE_MANAGED_CAS_CA --backup-start-time=09:00 --retained-backups-count=2 --database-flags=max_connections=100
--server-ca-mode=GOOGLE_MANAGED_CAS_CA matters. With the default per-instance CA the server
certificate carries no DNS name, and the Console and the Gateway cannot verify it.
max_connections must cover the key server's pool (32 connections) and the Console's and the
Gateway's audit pools.
Then create the key database and its role. Put the role's password in a gcloud flags file (mode 600), so it is never on a command line:
gcloud sql databases create <database> --instance=<instance>
gcloud sql users create <role> --instance=<instance> --flags-file=<password-flags.yaml>
<password-flags.yaml> holds one line, --password: <password>. Use letters and digits only.
Keep the same password in a file on the VM, owned by root, mode 600, for the provisioner.
Read the three values the key server needs: the server CA chain, the name its certificate is issued to, and the private address:
gcloud sql ssl server-ca-certs list --instance=<instance> --format="value(cert)" > server-ca.pem
gcloud sql instances describe <instance> --format="value(dnsNames[0].name)"
gcloud sql instances describe <instance> --format="value(ipAddresses[0].type,ipAddresses[0].ipAddress)"
server-ca.pem holds two certificates, the regional subordinate and Google's root. The DNS
name ends in a dot. Keep the dot: the certificate carries it, and libpq compares the name
exactly.
2. Create the VM and reach it
gcloud compute instances create <vm> --zone=<zone> --machine-type=e2-standard-4 --subnet=<subnet> --no-address --image-family=ubuntu-2404-lts-amd64 --image-project=ubuntu-os-cloud --boot-disk-size=100GB --boot-disk-type=pd-balanced --shielded-secure-boot --shielded-vtpm --shielded-integrity-monitoring --metadata=enable-oslogin=TRUE --no-service-account --no-scopes
gcloud compute start-iap-tunnel <vm> 22 --local-host-port=localhost:<local-port> --zone=<zone>
Then ssh -p <local-port> to localhost as your OS Login user, and forward the Console
(18090), the Gateway (18091) and the key server (8893) through that session when you
need them. Copy server-ca.pem to the VM, readable by the service user and outside
/etc/pisoft: apt purge removes that directory only when it holds nothing but what
provisioning wrote there.
3. Install and provision on the VM
Install the packages as on any Ubuntu host. Then provision the key server against the instance. The database host is the private address, and the certificate is checked against the DNS name:
sudo tricryption-ks-provision --xauth-policy --db <database> --db-role <role> --db-host <private-address> --db-password-file <db-password-file> --db-sslmode verify-full --db-sslrootcert <server-ca.pem> --db-servername <dns-name>
The provisioner creates nothing on the instance. The database must exist and be empty, and
the role must log in. It prints database TLS: sslmode=verify-full, the server reports ssl|version = t|TLSv1.3 before it writes the configuration. It also checks that the
generated configuration names the address as the server and the DNS name as the certificate's
name. The key server verifies the certificate against the name, and connects to the address.
Then provision the Console and the Gateway beside it as in step 3 of the Linux page:
sudo tricryption-tier-provision --signer-cert <signer.pem> --signer-ca <release-ca.pem> --signer-crl <release-ca.crl.der>
The tool takes the database's address, mode, CA and name from the key server's record, so the
Console's and the Gateway's audit readers reach the same instance over verify-full. Each logs
[boot] audit database TRANSPORT: VERIFIED (verify-full) with the name it checked.
If the key server cannot verify the database's certificate, it does not start. Its journal
says SSL error: certificate verify failed, and it opens no session on the instance.
The MCP server on the VM
The Console package ships the MCP server with the Python
starter, under /opt/pisoft/tricryption/console-gateway/examples/python-agent-starter. Canonical's
Ubuntu 24.04 image has no venv module for its Python. Install it only if python3 -c 'import ensurepip' fails, then install the SDK from the shipped hash lock:
sudo apt-get install -y python3-venv
python3 -m venv ~/te-mcp/venv
~/te-mcp/venv/bin/python -m pip install --require-hashes --no-deps -r /opt/pisoft/tricryption/console-gateway/examples/python-agent-starter/mcp/requirements.lock
Without an identity provider, run one MCP server per user, each with its own task grant naming that user, beside the Gateway on the VM. To hand a section to another user, the first user's grant names the step.
Verifying a release
Check the packages against the release's signed SHA256SUMS on the VM before you install them.
See Verifying a release.
Upgrading
Install the newer release's packages on the VM. The packages restart what was running. At code-signing level 2, then register the new release:
sudo tricryption-tier-provision --register-release --signer-cert <signer.pem> --signer-ca <release-ca.pem> --signer-crl <release-ca.crl.der>
See Upgrade on Linux.
Register the newer release before you raise the code-signing level. If you raise it first, the level takes effect, and the Console refuses its own requests until the release is registered.
Removing
apt-get remove and apt-get purge work as on any Ubuntu host. Neither
touches the key database on Cloud SQL: it is your data. To delete the instance itself:
gcloud sql instances delete <instance>
What was qualified, and what was not
On 2026-10-29 the shape above was qualified again, in a fresh environment in one zone, with
release 8.1.0+3647.gafc556ab installed fresh: Compute Engine e2-standard-4 on
ubuntu-2404-noble-amd64-v20261024, and Cloud SQL for PostgreSQL 16.15 db-custom-2-8192, zonal,
in the VM's zone, over verify-full. This release carries Node.js 24.22.2 (see the
security advisory). Everything the earlier runs
checked, listed below, passed again on it, and also:
- the installed
/opt/pisoft/tricryption/node/bin/nodeanswersv24.22.2, byte for byte the runtime nodejs.org publishes, and both the Console and the Gateway run on it; - Brotli-encoded request bodies sent to the installed Gateway and Console were refused as the
bytes they are,
400 BAD_REQUESTwith or withoutContent-Encoding: br, and both stayed up.
This run had one release, so it did not include an upgrade; the cell below was upgraded to this release.
On 2026-10-26 the shape above was qualified again, in a fresh environment in one zone: Compute
Engine e2-standard-4 on ubuntu-2404-noble-amd64-v20261024, and Cloud SQL for PostgreSQL 16.15
db-custom-2-8192, zonal, in the VM's zone, over verify-full. Release 8.1.0+3507.g8a95ed57
was installed fresh and upgraded to 8.1.0+3517.g7ed8e8fa at code-signing level 2, then to
8.1.0+3527.gc378cec4. Everything the 2026-10-20 run checked, listed below, passed again. Also:
- the MCP server shipped with the Console, run on the VM from the installed package, one server per user over stdio: a compound document read whole by its owner and as a mixed view by a second user, a section handed to that user for one step and opened, the other sections refused by the key server, and the section refused again once the step was closed;
- the encrypt size limit, where 16,777,215 bytes encrypt and decrypt intact and one byte more is
refused with
400before the key server is asked; - a request refused by a key's access list leaving its audit row, naming that key, in the key database on Cloud SQL.
On 2026-10-20 the shape was first qualified in a fresh environment in one zone: Compute Engine
e2-standard-4 on ubuntu-2404-noble-amd64-v20261016, and Cloud SQL for PostgreSQL 16
db-custom-2-8192, zonal, in the VM's zone, over verify-full. The release was installed and
upgraded to the next build at code-signing level 2. The checks covered:
- install, provisioning and readiness, and the acceptance suite;
- the database's identity, TLS on the key-server path and the Node path, and privacy (each
with a refusal beside it: a wrong CA, a wrong name and
sslmode=disable); - the running key server refusing a database CA it does not trust;
- sessions killed on the database, a database restart, and a write interrupted in flight;
- a reboot, a stop and start, and a reboot with the database held stopped;
- the release checksums and signature;
- upgrade, the level-2 upgrade, a changed payload byte refused at admission, removal and reinstall, and purge with the database untouched;
- the remote engine, the Python starter through the delegation layer, and Java code signing against this key server.
The Cloud SQL Auth Proxy, a public address on the instance, and the Gateway and the Console on another Google Cloud service were not part of the run.
Qualified at engine master afc556ab71cf.
Several key servers behind one address, on a regional instance
The shape above runs one key server. For availability, run several key servers on one regional
Cloud SQL instance behind one internal passthrough Network Load Balancer, as
Scaling and high availability describes: one
unmanaged instance group per zone, a regional TCP health check on the key servers' port, a
regional internal TCP backend service, a reserved internal address, a forwarding rule on that
port, and a firewall rule admitting the health-check ranges 35.191.0.0/16 and
130.211.0.0/22 and the clients' subnet. Every key server listens on 0.0.0.0 on that one port.
On 2026-10-20 this shape was qualified: three key servers on e2-standard-4 in two zones, a
regional db-custom-2-8192 instance (primary in the first zone, standby in the second) over
verify-full, and the Console and the Gateway on their own VM addressing the load balancer. The
run covered adding, removing and replacing a key server, a key server killed, a zone lost, the
database failed over to its standby and back, the whole cell lost and recovered onto a new
instance, and a rolling upgrade at code-signing level 2, each with a client making a fresh
request about once a second; that page gives what each one cost.
On 2026-10-26 the shape was qualified again on image ubuntu-2404-noble-amd64-v20261024: installed
from the 2026-10-20 release and rolled, without being taken down, to 8.1.0+3507 (signed by another
signer, registered first) and on to 8.1.0+3538 at code-signing level 2, with no request of the
client failed during either roll. A cell that relies on CRL revocation runs 8.1.0+3538 or later.
On 2026-10-27 it was qualified again: installed from 8.1.0+3507 and rolled, without being taken down, to 8.1.0+3578 (signed by another signer, registered first) at code-signing level 2, with no request of the client failed during the roll. On 8.1.0+3578 a key expired or removed through one key server is refused at its next use on every other key server.
On 2026-10-29 it was qualified again: installed from 8.1.0+3578 and rolled, without being taken
down, to 8.1.0+3647 (Node.js 24.22.2; signed by another signer, registered first) at code-signing
level 2, with no request of the client failed during the roll. On 8.1.0+3647 a ciphertext that does
not decrypt is answered 422 DECRYPT_FAILED by every key server.
Qualified at engine master afc556ab71cf.