GitHub

FileMage SFTP Gateway

THB’s managed SFTP + web portal for partner file exchange, backed by GCS.

Three hostnames:

  • sftp.thehelperbees.com — SFTP for partners, port 22. Un-proxied A record direct to VM IP.
  • sftp.thb.nu — Workspace portal (THB users). Cloudflare tunnel + Access, 168h session.
  • admin.sftp.thb.nu — Management portal (admins). Same tunnel, separate Access app, 24h session.

Common operations

Deploy VM-side config

./zig/zig build scripts -- deploy_filemage

Idempotent. Use after tunnel token or SendGrid rotations, or SMTP config changes.

SSH to the VM (IAP tunnel)

Requires roles/iap.tunnelResourceAccessor on prj-bu1-c-common-infra-c4aa (granted to sg-hb-infra-development@thehelperbees.com and sg-developers@thehelperbees.com in gcp-projects/business_unit_1/shared/common_infra.tf).

gcloud compute ssh filemage-sftp-vm \
  --zone=us-central1-b --project=prj-bu1-c-common-infra-c4aa \
  --tunnel-through-iap --ssh-flag="-p 2222"

Serial console is enabled as the last-resort path if IAP is down:

gcloud compute connect-to-serial-port filemage-sftp-vm \
  --zone=us-central1-b --project=prj-bu1-c-common-infra-c4aa

Rotate the Cloudflare tunnel token

echo -n "<new-token>" | gcloud secrets versions add filemage-tunnel-token \
  --project=prj-bu1-c-common-infra-c4aa --data-file=-
./zig/zig build scripts -- deploy_filemage

Rotate the SendGrid API key

echo -n "<new-key>" | gcloud secrets versions add filemage_sendgrid_api_secret \
  --project=prj-c-secrets-a7cc --data-file=-
./zig/zig build scripts -- deploy_filemage

Attach the reserved static IP

After the reserved IP is first created, or after a Marketplace re-apply flipped the VM back to ephemeral:

NEW_IP=$(gcloud compute addresses describe filemage-sftp-ip \
  --region=us-central1 --project=prj-bu1-c-common-infra-c4aa \
  --format="value(address)")

gcloud compute instances delete-access-config filemage-sftp-vm \
  --zone=us-central1-b --project=prj-bu1-c-common-infra-c4aa \
  --access-config-name=external-nat

gcloud compute instances add-access-config filemage-sftp-vm \
  --zone=us-central1-b --project=prj-bu1-c-common-infra-c4aa \
  --access-config-name=external-nat --address=$NEW_IP

Admin locked out

SSH to VM, run sudo filemage reset.

Update FileMage

Monthly cadence. Opt-in flag on deploy_filemage. Before:

# Confirm recent snapshot
gcloud compute snapshots list --project=prj-bu1-c-common-infra-c4aa \
  --filter="sourcePolicies:filemage-sftp-daily-snapshot" --limit=3

# On-demand pg_dump (logical backup survives schema changes better than disk snapshot)
gcloud compute ssh filemage-sftp-vm --project=prj-bu1-c-common-infra-c4aa --zone=us-central1-b \
  -- 'sudo -u postgres pg_dump filemage | sudo tee /var/backups/filemage-$(date +%Y%m%d).sql > /dev/null'

Run the update (runs sudo filemage update -y, then re-asserts the managed config block in case the update overwrote /etc/filemage/config.yml):

./zig/zig build scripts -- deploy_filemage --update

Rollback: restore boot disk from snapshot, or restore DB with sudo -u postgres psql filemage < /var/backups/filemage-<date>.sql.

Emergency access

Partners can’t reach SFTP:

  1. dig +short sftp.thehelperbees.com — must return the reserved static IP. Cloudflare proxy IPs (104.x / 172.67.x) mean the DNS record got flipped to proxied; fix in TF.
  2. gcloud compute instances describe filemage-sftp-vm --zone=us-central1-b --format="value(networkInterfaces[0].accessConfigs[0].natIP)" — must match the reserved IP. If not, run “Attach the reserved static IP.”
  3. nc -zv <static-ip> 22 from an external host. If it fails, check the filemage-sftp-tcp-22 firewall rule and systemctl status filemage on the VM. sudo ss -tlnp | grep :22 on the VM should show gateway (FileMage) as the listener — not sshd. If sshd is on :22, the port migration didn’t apply; re-run ./zig/zig build scripts -- deploy_filemage.

THB users can’t reach the portals:

  1. Cloudflare dashboard → Zero Trust → Networks → Tunnels → filemage — connectors must be healthy.
  2. Zero Trust → Access → Applications — confirm the app + policy are enabled.
  3. On the VM: systemctl status cloudflared, sudo cat /etc/cloudflared/token matches latest secret version.
  4. Re-run deploy_filemage from VPN.
  5. Admin break-glass: VPN → https://<static-ip>:8443 direct.

VM is down: gcloud compute instances describe filemage-sftp-vm --zone=us-central1-b. Before rebuilding from Marketplace, coordinate with DevOps — a rebuild loses the Postgres user DB.

Architecture

VM provisioned via GCP Marketplace (filemage-sftp Infrastructure Manager deployment). Not in Terraform. Don’t re-apply the Marketplace deployment — it destroys the Postgres DB and resets the admin password. To remove Marketplace without killing the VM:

gcloud infra-manager deployments delete filemage-sftp \
  --project=prj-bu1-c-common-infra-c4aa --location=us-central1 --delete-policy=abandon

On-VM services (deployed by ./zig/zig build scripts -- deploy_filemage):

  • filemage — gateway. Config at /etc/filemage/config.yml.
  • cloudflared — tunnel to Cloudflare.
  • remote_syslog — forwards /var/log/filemage/*.log to Papertrail.
  • falcon-sensor — CrowdStrike endpoint security.

Terraform: infra/common-infra/business_unit_1/shared/filemage.tf.

External references

Edit this page