Onboarding: connect your data
shaft runs the ingestion agent on our infrastructure. To let it read from your database and write to your BigQuery, you grant it access from your side — no software to install, and no secret keys ever leave your environment. You can revoke everything at any time.
There are two grants: (1) let our agent reach your source database, and (2) let our service account write to your BigQuery. Both are below.
1. Allow shaft's IP to reach your database
Our agent connects outbound from a fixed IP address:
34.185.215.106
Add it to your database's allowlist (/32 = just this one address). We'll
notify you in advance if it ever changes.
Cloud SQL (Postgres / MySQL) Instance → Connections → Networking → Authorized networks → add:
34.185.215.106/32
Self-managed Postgres / MySQL
-
Open the DB port to that IP in your firewall / security group (Postgres
5432, MySQL3306), inbound from34.185.215.106/32. -
Postgres also needs a
pg_hba.confline, e.g.:host yourdb shaft 34.185.215.106/32 scram-sha-256
Prefer not to expose the database to the internet? shaft also supports an SSH tunnel or the shaft proxy — see those docs and skip this step.
2. Create a database user for shaft
Create a dedicated login with read-only access to the tables you want to sync:
CREATE USER shaft WITH PASSWORD 'a-strong-password';
GRANT CONNECT ON DATABASE yourdb TO shaft;
GRANT USAGE ON SCHEMA public TO shaft;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO shaft;
For change-data-capture (CDC / streaming) sources, the user also needs replication and logical decoding:
- Cloud SQL Postgres: set the flag
cloudsql.logical_decoding=on, thenALTER USER shaft WITH REPLICATION; ALTER TABLE your_table REPLICA IDENTITY FULL; -- full before/after images - Self-managed Postgres:
wal_level=logicalandALTER ROLE shaft WITH REPLICATION;
You'll enter the connection URL and this user/password when you create the source connector in the portal — or authenticate with shaft's service account instead of a password (see the next section).
Keyless option: authenticate with shaft's service account (IAM)
For Cloud SQL Postgres you can skip the password entirely: shaft logs in with its own Google service account using a short-lived IAM token — nothing secret is stored. Choose Service account identity (IAM) as the auth method on the source connector, then set this up on your instance:
- Enable IAM authentication — set the instance flag
cloudsql.iam_authentication=on. - Grant shaft's service account the Cloud SQL roles in your project:
gcloud projects add-iam-policy-binding YOUR_PROJECT_ID \ --member=serviceAccount:shaft-agent@coreshaft-prod.iam.gserviceaccount.com \ --role=roles/cloudsql.client gcloud projects add-iam-policy-binding YOUR_PROJECT_ID \ --member=serviceAccount:shaft-agent@coreshaft-prod.iam.gserviceaccount.com \ --role=roles/cloudsql.instanceUser - Create the IAM database user for it, then grant it read access:
Cloud SQL registers the DB role without thegcloud sql users create shaft-agent@coreshaft-prod.iam.gserviceaccount.com \ --instance=YOUR_INSTANCE --type=cloud_iam_service_account.gserviceaccount.comsuffix, so connect to the database and grant that name (addREPLICATIONtoo if you'll use streaming/CDC):GRANT CONNECT ON DATABASE yourdb TO "shaft-agent@coreshaft-prod.iam"; GRANT USAGE ON SCHEMA public TO "shaft-agent@coreshaft-prod.iam"; GRANT SELECT ON ALL TABLES IN SCHEMA public TO "shaft-agent@coreshaft-prod.iam"; ALTER ROLE "shaft-agent@coreshaft-prod.iam" WITH REPLICATION; -- for CDC - In the connector, enter
shaft-agent@coreshaft-prod.iamas the Database user / service account. No password is asked for.
IAM works for both query-based sync and CDC — verified on Cloud SQL Postgres with
cloudsql.logical_decoding+cloudsql.iam_authenticationon. For streaming (CDC), grant the IAM role theREPLICATIONattribute (theALTER ROLE … WITH REPLICATIONline above). You still authorize the IP (section 1).
3. Grant shaft access to your BigQuery
shaft writes to BigQuery as its own Google service account:
shaft-agent@coreshaft-prod.iam.gserviceaccount.com
Grant that service account two roles in your project — nothing is shared with us, you're only authorizing our identity:
| Role | Where | Why |
|------|-------|-----|
| roles/bigquery.jobUser | project | run the load/insert jobs |
| roles/bigquery.dataEditor | the target dataset | write rows into your tables |
With gcloud:
# 1) job runner (project level)
gcloud projects add-iam-policy-binding YOUR_PROJECT_ID \
--member="serviceAccount:shaft-agent@coreshaft-prod.iam.gserviceaccount.com" \
--role="roles/bigquery.jobUser"
# 2) write access (dataset level — least privilege)
bq add-iam-policy-binding \
--member="serviceAccount:shaft-agent@coreshaft-prod.iam.gserviceaccount.com" \
--role="roles/bigquery.dataEditor" \
YOUR_PROJECT_ID:YOUR_DATASET
In the Cloud Console: IAM & Admin → Grant access → paste the service account email → add the two roles above.
Also make sure the BigQuery API is enabled in your project
(bigquery.googleapis.com — on by default for most projects) and the target
dataset exists. shaft creates the target table for you if it's missing:
- Raw mode (a raw column set on the connector): the table is created as
(rawColumn STRING, _op STRING, _table STRING)and each change lands as JSON — model it into typed views downstream. Nothing to define. - Typed mode: paste a BigQuery schema JSON on the connector (the same
[{"name":"id","type":"INT64","mode":"REQUIRED"}, …]formatbquses) and shaft creates the table with exactly those columns.
Prefer stricter isolation? (impersonation)
If your policy doesn't allow granting an external service account directly, you can keep the identity entirely on your side:
-
Create a service account in your project and give it the two BigQuery roles above.
-
Grant our service account permission to impersonate it:
gcloud iam service-accounts add-iam-policy-binding \ YOUR_SA@YOUR_PROJECT_ID.iam.gserviceaccount.com \ --member="serviceAccount:shaft-agent@coreshaft-prod.iam.gserviceaccount.com" \ --role="roles/iam.serviceAccountTokenCreator" -
Tell us that service account's email — we set it on your BigQuery connector, and shaft writes as your own identity.
Checklist
- [ ] Added
34.185.215.106/32to the database allowlist (or set up SSH tunnel / proxy) - [ ] Created the
shaftDB user (withREPLICATIONif using CDC) - [ ] Granted
bigquery.jobUser+bigquery.dataEditortoshaft-agent@coreshaft-prod.iam.gserviceaccount.com(or set up impersonation) - [ ] BigQuery API enabled and the target dataset created (shaft creates the table)
Once these are in place, create your source and BigQuery connectors in the portal, pair them into a pipeline, and shaft starts moving your data. To stop access, remove the IP from the allowlist and the IAM bindings — nothing else lives in your environment.