DIY Google Workspace encryption for ~$0.10/month
β οΈ IMPORTANT DISCLAIMER: TinyVault is an unaudited, open-source project for personal use and learning. It has NOT been professionally audited or certified for compliance (HIPAA, PCI, FedRAMP, etc.). While it uses secure Google Cloud components, TinyVault itself is a DIY solution. Use at your own risk. For mission-critical or regulated data, consider professionally audited enterprise solutions.
TinyVault is a lightweight, self-hosted KACLS endpoint for Google Workspace Client-Side Encryption (CSE). It enables you to encrypt Gmail, Drive, Calendar, and Meet content with your own encryption keysβwithout paying thousands of dollars for enterprise CSE partner solutions.
Best for: Personal use, small teams, learning, non-critical data NOT for: HIPAA/PCI/regulated data (without your own compliance work), mission-critical enterprise use (without hardening)
Google Workspace CSE requires a third-party key service. Google's official partners charge:
- $10-30 per user/month minimum
- Enterprise-only pricing (often 50+ user minimums)
- Annual contracts starting at $6,000+
For individuals or small teams, this is prohibitively expensive.
TinyVault lets you run your own CSE endpoint for ~$0.10-0.50/month using:
- Google Cloud Run (serverless, free tier available)
- Google Cloud KMS (secure key storage, FIPS 140-2 validated)
- Your own infrastructure and control
- π Secure: Uses Google Cloud KMS for key management (FIPS 140-2 validated)
- π° Cheap: Runs in Cloud Run free tier (~$0.10-0.50/month for single user)
- π Simple: Deploy in under 5 minutes with automated scripts
- π Custom Domains: Professional setup with your own domain
- π³ Docker Ready: Pre-built containers on Docker Hub
- π Well Documented: Comprehensive guides and troubleshooting
- π Open Source: MIT licensed, contribute and customize freely
- Google Cloud Account with billing enabled (free tier works)
- Google Workspace account (Business Standard or higher for CSE support)
- gcloud CLI installed (installation guide)
- Admin access to Google Workspace Admin Console
# Clone the repository
git clone https://github.com/shawntz/tinyvault.git
cd tinyvault
# Run setup script
chmod +x setup.sh deploy.sh
./setup.sh
# Deploy to Cloud Run
./deploy.shThe deployment script will:
- β Build and deploy to Cloud Run
- β Configure environment variables
- β
Optionally set up custom domain (e.g.,
secure.yourdomain.com) - β Provide your KACLS endpoint URL
Skip building! Deploy the pre-built Docker image directly to Cloud Run:
# Clone the repository
git clone https://github.com/shawntz/tinyvault.git
cd tinyvault
# Run setup (one time only)
chmod +x setup.sh deploy-dockerhub.sh
./setup.sh
# Deploy from Docker Hub
./deploy-dockerhub.shThis is faster than Option 1 since it pulls the pre-built image instead of building on Cloud Run.
# Pull the image
docker pull shawnschwartz/tinyvault:latest
# Run with your configuration
docker run -d \
-p 8080:8080 \
-e GCP_PROJECT_ID=your-project \
-e KMS_LOCATION=us-central1 \
-e KMS_KEYRING=cse-keyring \
-e KMS_KEY=cse-key \
-e [email protected] \
-v /path/to/service-account.json:/app/key.json \
-e GOOGLE_APPLICATION_CREDENTIALS=/app/key.json \
--name tinyvault \
shawnschwartz/tinyvault:latestSee DOCKER.md for full Docker documentation.
Run the setup script to configure GCP resources:
./setup.shThis will:
- Enable required GCP APIs (Cloud KMS, Cloud Run, Cloud Build)
- Create KMS key ring and encryption key
- Generate example configuration file
You'll be prompted for:
- GCP Project ID
- KMS location (default:
us-central1) - Your email address for authorization
./deploy.shDuring deployment, you'll configure:
- Cloud Run region
- Service name
- Custom domain (optional but recommended)
Recommended: Use a custom subdomain like:
secure.yourdomain.com(default, privacy-focused)vault.yourdomain.com(security-focused)cse.yourdomain.com(technical)
The script handles domain mapping and provides DNS instructions.
Add this CNAME record at your DNS provider:
Type: CNAME
Name: secure (or your chosen subdomain)
Value: ghs.googlehosted.com
TTL: 3600
Cloud Run will automatically provision an SSL certificate via Let's Encrypt (5-15 minutes).
# Test health endpoint
curl https://secure.yourdomain.com/health
# Should return: {"status":"healthy"}- Go to Google Workspace Admin Console (admin.google.com)
- Navigate to: Security > Access and data control > Data protection > Client-side encryption
- Click Add external key service
- Enter:
- Service name: TinyVault (or any name)
- Service URL:
https://secure.yourdomain.com - Authentication: OAuth 2.0
- Test the connection (should succeed)
- Enable CSE for your account
Gmail:
- Compose a new email
- Click the lock icon > "Additional encryption"
- Select your TinyVault key service
- Compose and send encrypted email
Google Drive:
- Create or upload a document
- Click Share > Advanced > "Client-side encryption"
- Select TinyVault
- Share securely
| Variable | Description | Example |
|---|---|---|
GCP_PROJECT_ID |
Your GCP project ID | my-project-123456 |
KMS_LOCATION |
KMS key location | us-central1 |
KMS_KEYRING |
KMS key ring name | cse-keyring |
KMS_KEY |
KMS crypto key name | cse-key |
ALLOWED_EMAILS |
Comma-separated authorized emails | [email protected],[email protected] |
PORT |
Service port (Cloud Run sets automatically) | 8080 |
Update the Cloud Run service to add more authorized emails:
gcloud run services update cse-kacls \
--region us-central1 \
--set-env-vars "[email protected],[email protected],[email protected]"Check domain mapping status:
gcloud run domain-mappings describe secure.yourdomain.com --region us-central1Update or remove domain mapping:
# Remove domain
gcloud run domain-mappings delete secure.yourdomain.com --region us-central1
# Add new domain
gcloud run domain-mappings create \
--service cse-kacls \
--domain new-subdomain.yourdomain.com \
--region us-central1βββββββββββββββββββ
β Google Workspaceβ
β (Gmail, Drive) β
ββββββββββ¬βββββββββ
β KACLS Protocol
β (wrap/unwrap keys)
βΌ
βββββββββββββββββββ
β TinyVault β
β (Cloud Run) β
β - Flask API β
β - OAuth2 auth β
ββββββββββ¬βββββββββ
β
β Encrypt/Decrypt
βΌ
βββββββββββββββββββ
β Google Cloud KMSβ
β (Master Keys) β
βββββββββββββββββββ
- Client-side encryption: Google Workspace encrypts content in your browser/app with a Data Encryption Key (DEK)
- Key wrapping: Workspace calls TinyVault to wrap (encrypt) the DEK
- KMS encryption: TinyVault uses Google Cloud KMS to encrypt the DEK with your master key
- Storage: Wrapped DEK is stored with the encrypted content
- Decryption: Reverse process to unwrap and decrypt content
Important: Your master encryption key never leaves Google Cloud KMS. All operations happen securely within Google's infrastructure.
Current Status:
TinyVault is:
- β NOT security audited by third-party professionals
- β NOT penetration tested
- β NOT certified for any compliance framework (HIPAA, PCI, FedRAMP, SOC 2, etc.)
- β NOT recommended for production enterprise use without significant hardening
- β NOT a replacement for professionally audited enterprise CSE solutions
TinyVault IS:
- β Good for: Personal use, learning, experimentation, non-critical data
- β Open source: Code is transparent and auditable (by you or security professionals you hire)
- β Based on secure components: Uses Google Cloud KMS and Cloud Run
If you need compliance certification, you are responsible for:
- Hiring security auditors
- Penetration testing
- Code review
- Compliance documentation
- Risk assessment
- Incident response planning
The underlying Google Cloud infrastructure TinyVault uses:
Google Cloud KMS (where keys are stored):
- β FIPS 140-2 Level 3 validated hardware security modules
- β ISO/IEC 27001 certified
- β SOC 2/3 compliant
- β HIPAA eligible (with BAA)
- β PCI DSS compliant
Google Cloud Run (where TinyVault runs):
- β HTTPS enforced (TLS 1.2+)
- β Automatic SSL certificates
- β ISO 27001, SOC 2/3 certified
- β Infrastructure security managed by Google
TinyVault application code:
β οΈ No professional security auditβ οΈ No penetration testingβ οΈ No formal threat modelingβ οΈ No security certificationsβ οΈ Minimal input validationβ οΈ No rate limiting by defaultβ οΈ No WAF (Web Application Firewall) by defaultβ οΈ Unauthenticated Cloud Run endpoint (by design for KACLS protocol)
What's good:
- β Master encryption keys never leave Google Cloud KMS (FIPS 140-2 validated HSMs)
- β Keys are never exposed to the application or stored anywhere except KMS
- β OAuth2 token verification for incoming requests
- β Email-based authorization (restrict to specific users)
- β All KMS operations logged via Cloud Audit Logs
- β HTTPS-only connections enforced by Cloud Run
- β Encrypted data at rest (wrapped DEKs stored with encrypted content)
What could be better:
β οΈ No rate limiting (could be DDoS'd)β οΈ Cloud Run endpoint is public (required for Google Workspace, but increases attack surface)β οΈ No request signing/validation beyond OAuth2 tokenβ οΈ No anomaly detectionβ οΈ No intrusion detectionβ οΈ Minimal monitoring by default
- Current security is adequate
- Follow the basic security checklist below
- Accept that this is DIY software
- Current security is marginal
- Add: Rate limiting, WAF (Cloud Armor), monitoring alerts
- Consider: Security code review by a professional
- Accept risk: This is not enterprise-grade
- Current security is insufficient
- Required: Full security audit, penetration testing, compliance documentation
- Required: Hire security professionals to harden
- Recommended: Use a professionally audited CSE partner instead
Before using TinyVault, at minimum:
- Set
ALLOWED_EMAILSto specific users (never leave empty) - Use a custom domain with SSL
- Enable Cloud Audit Logs for KMS
- Set up alerting for unusual KMS activity
- Review Cloud Run logs weekly
- Use least-privilege IAM roles
- Keep dependencies updated (Dependabot helps automatically)
- Review and merge Dependabot security PRs promptly
- Monitor GitHub Security tab for alerts
- Understand you're using unaudited software
- Have a backup plan if TinyVault fails
- Don't use for data you can't afford to lose access to
TinyVault includes automated security scanning to help catch vulnerabilities:
- β Weekly dependency updates for Python, Docker, GitHub Actions
- β Automatic security patch PRs when vulnerabilities are found
- β Groups minor/patch updates to reduce PR noise
- π Configuration:
.github/dependabot.yml
- β Automatic code scanning on every push and PR
- β Weekly scheduled scans for new vulnerability patterns
- β Detects: SQL injection, XSS, insecure crypto, etc.
- π Configuration:
.github/workflows/security.yml
- β Blocks PRs with high-severity vulnerabilities
- β Automatic comments on PRs with security findings
- β Runs on all pull requests
- β Safety: Checks dependencies against CVE database
- β Bandit: Static analysis for Python security issues
- β Generates reports as artifacts
View alerts: https://github.com/shawntz/tinyvault/security
Important:
| Service | Usage | Cost/Month |
|---|---|---|
| Cloud Run | ~1000 requests | $0.00 (free tier) |
| Cloud KMS | Key storage | $0.06 |
| Cloud KMS | ~1000 operations | $0.00 (free tier) |
| Total | ~$0.06-0.10 |
| Service | Usage | Cost/Month |
|---|---|---|
| Cloud Run | ~5000 requests | $0.00 (free tier) |
| Cloud KMS | Key storage | $0.06 |
| Cloud KMS | ~5000 operations | $0.02 |
| Total | ~$0.08-0.20 |
- Cloud Run: 2M requests/month, 360,000 GB-seconds compute
- Cloud KMS: 20,000 operations/month (encrypt/decrypt)
You'll likely stay in free tier unless you have >10 active users.
| Solution | Cost (1 user/year) | Cost (5 users/year) |
|---|---|---|
| TinyVault | $1-2 | $2-5 |
| Enterprise CSE Partner | $120-360 | $600-1800 |
| Savings | 99% | 99% |
TinyVault implements the Google Workspace KACLS protocol:
Health check endpoint for monitoring.
Response:
{"status": "healthy"}Wraps (encrypts) a data encryption key using KMS.
Request:
{
"key": "base64-encoded-plaintext-DEK",
"authorization": {
"resource_name": "resource-identifier",
"user_email": "[email protected]"
}
}Response:
{
"wrappedKey": "base64-encoded-wrapped-DEK",
"status": "success"
}Unwraps (decrypts) a data encryption key using KMS.
Request:
{
"wrappedKey": "base64-encoded-wrapped-DEK",
"authorization": {
"resource_name": "resource-identifier",
"user_email": "[email protected]"
}
}Response:
{
"key": "base64-encoded-plaintext-DEK",
"status": "success"
}Admin unwrap for privileged access scenarios (e.g., compliance, audit).
Request:
{
"wrappedKey": "base64-encoded-wrapped-DEK",
"reason": "Legal hold request #12345"
}Response:
{
"key": "base64-encoded-plaintext-DEK",
"status": "success"
}docker pull shawnschwartz/tinyvault:latest# Using service account key
docker run -d \
-p 8080:8080 \
-e GCP_PROJECT_ID=your-project \
-e KMS_LOCATION=us-central1 \
-e KMS_KEYRING=cse-keyring \
-e KMS_KEY=cse-key \
-e [email protected] \
-v $(pwd)/service-account-key.json:/app/key.json \
-e GOOGLE_APPLICATION_CREDENTIALS=/app/key.json \
--name tinyvault \
shawnschwartz/tinyvault:latestservices:
tinyvault:
image: shawnschwartz/tinyvault:latest
ports:
- "8080:8080"
environment:
- GCP_PROJECT_ID=your-project
- KMS_LOCATION=us-central1
- KMS_KEYRING=cse-keyring
- KMS_KEY=cse-key
- [email protected]
- GOOGLE_APPLICATION_CREDENTIALS=/app/key.json
volumes:
- ./service-account-key.json:/app/key.json:ro
restart: unless-stoppedSee DOCKER.md for complete Docker documentation.
# Cloud Run logs
gcloud run logs read cse-kacls --region us-central1 --limit 50
# KMS audit logs
gcloud logging read "resource.type=cloudkms_cryptokeyversion" --limit 50
# Filter for errors
gcloud run logs read cse-kacls --region us-central1 | grep ERRORCreate Cloud Monitoring alerts for:
- High error rate (>5% of requests failing)
- Unusual KMS activity (sudden spike in operations)
- Unauthorized access attempts (401/403 responses)
# Example: Alert on error rate
gcloud alpha monitoring policies create \
--notification-channels=YOUR_CHANNEL_ID \
--display-name="TinyVault Error Rate" \
--condition-threshold-value=0.05 \
--condition-display-name="Error rate > 5%"Monitor via Cloud Console:
- Request count
- Request latency (p50, p95, p99)
- Error rate
- Container instance count
- KMS operation count
Fix: Grant the Cloud Run service account KMS permissions:
# Get service account email
gcloud run services describe cse-kacls \
--region us-central1 \
--format="value(spec.template.spec.serviceAccountName)"
# Grant KMS permissions
gcloud kms keys add-iam-policy-binding cse-key \
--location us-central1 \
--keyring cse-keyring \
--member serviceAccount:[email protected] \
--role roles/cloudkms.cryptoKeyEncrypterDecrypter- Verify endpoint is accessible:
curl https://your-url/health - Check Cloud Run allows unauthenticated access (required for Workspace to connect)
- Review Cloud Run logs for errors during connection test
- Ensure
ALLOWED_EMAILSincludes the test user's email
Check that ALLOWED_EMAILS matches the email in the OAuth token:
gcloud run services describe cse-kacls \
--region us-central1 \
--format="value(spec.template.spec.containers[0].env)"- Verify DNS record is correct:
dig secure.yourdomain.com - Wait 15-30 minutes for DNS propagation
- Check domain mapping status:
gcloud run domain-mappings describe secure.yourdomain.com --region us-central1
- Ensure domain is verified in Google Search Console
Check operation count:
gcloud logging read "resource.type=cloudkms_cryptokeyversion" \
--format="table(timestamp,protoPayload.methodName)" \
--freshness=30dIf unusually high:
- Review authorized users (compromised account?)
- Check for automated scripts making excessive requests
- Consider caching wrapped keys (advanced)
Run separate instances for dev/staging/prod:
# Deploy staging
gcloud run deploy cse-kacls-staging \
--source . \
--region us-central1 \
--set-env-vars "GCP_PROJECT_ID=project,KMS_KEYRING=cse-staging,..."
# Deploy production
gcloud run deploy cse-kacls \
--source . \
--region us-central1 \
--set-env-vars "GCP_PROJECT_ID=project,KMS_KEYRING=cse-prod,..."Rotate KMS keys periodically for security:
# Create new key version
gcloud kms keys versions create \
--key cse-key \
--keyring cse-keyring \
--location us-central1
# Set as primary
gcloud kms keys update cse-key \
--keyring cse-keyring \
--location us-central1 \
--primary-version VERSION_NUMBER
# Disable old version (after grace period)
gcloud kms keys versions disable OLD_VERSION \
--key cse-key \
--keyring cse-keyring \
--location us-central1Note: Old key versions must remain enabled to decrypt existing content.
Deploy to multiple regions for redundancy:
# Deploy to us-central1
gcloud run deploy cse-kacls --region us-central1 --source .
# Deploy to europe-west1
gcloud run deploy cse-kacls --region europe-west1 --source .
# Use Global Load Balancer to route trafficFor extra security, require IAM authentication:
# Remove public access
gcloud run services remove-iam-policy-binding cse-kacls \
--region us-central1 \
--member="allUsers" \
--role="roles/run.invoker"
# Grant specific service account
gcloud run services add-iam-policy-binding cse-kacls \
--region us-central1 \
--member="serviceAccount:[email protected]" \
--role="roles/run.invoker"Contributions welcome! Please:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
# Clone repo
git clone https://github.com/shawntz/tinyvault.git
cd tinyvault
# Install dependencies
pip install -r requirements.txt
# Set up environment
cp .env.example .env
nano .env
# Run locally
python app.py# Install dev dependencies
pip install pytest pytest-flask
# Run tests
pytest
# Run with coverage
pytest --cov=. --cov-report=htmlThis project is licensed under the MIT License - see the LICENSE file for details.
- β Use commercially
- β Modify and distribute
- β Private use
- β No warranty provided
- Google Cloud Platform for KMS and Cloud Run
- Google Workspace for CSE APIs
- The Flask community for excellent documentation
- Everyone who makes expensive software free and accessible
Not affiliated with Google. Google, Google Workspace, Google Cloud, Gmail, Google Drive, and Cloud Run are trademarks of Google LLC. TinyVault is an independent, open-source project.
This software is provided "AS IS" WITHOUT WARRANTY OF ANY KIND, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose, and noninfringement. See the MIT License for full terms.
β οΈ TinyVault has NOT been professionally security auditedβ οΈ TinyVault has NOT been penetration testedβ οΈ TinyVault is NOT certified for any compliance frameworkβ οΈ The authors and contributors are NOT liable for data loss, security breaches, or compliance failuresβ οΈ You are solely responsible for evaluating the security and suitability for your use case
You are responsible for:
- Understanding the security limitations
- Performing your own security assessment
- Implementing additional security controls as needed
- Maintaining and monitoring your deployment
- Compliance with applicable laws and regulations
- Data backup and disaster recovery
TinyVault is a DIY hobby project, not a professional managed service. There is:
- β No SLA (Service Level Agreement)
- β No guaranteed uptime
- β No professional support (community support only)
- β No liability for failures
- β No warranty of fitness for any particular use
Use TinyVault for:
- β Personal experimentation and learning
- β Non-critical data protection
- β Understanding how CSE works
- β Saving money on personal use cases
DO NOT use TinyVault for (without extensive hardening and professional security review):
- β HIPAA-protected health information
- β PCI DSS payment card data
- β Mission-critical business data
- β Data you can't afford to lose
- β Regulated financial data
- β Government classified information
- β Any compliance-required use case
Always:
- Test thoroughly with non-sensitive data first
- Understand how to recover if TinyVault fails
- Have backups of critical data
- Monitor logs and alerts
- Keep dependencies updated
- Review security best practices regularly
By using TinyVault, you acknowledge and accept these risks.
- Documentation: This README and inline code comments
- Issues: GitHub Issues
- Discussions: GitHub Discussions
For security vulnerabilities, please email: [[email protected]]
TinyVault uses automated date-based semantic versioning: YYYY.MM.PATCH
- YYYY: Year (e.g., 2025)
- MM: Month (01-12, zero-padded)
- PATCH: Auto-incrementing number for each release in that month
2025.01.0- First release in January 20252025.01.1- Second release in January 20252025.10.0- First release in October 2025
- Every push to
mainautomatically generates a new version - GitHub Actions calculates the version based on current date
- Auto-increments the patch number for the current month
- Creates a Git tag and GitHub release
- Builds and pushes Docker images with that version tag
Every release creates two Docker tags:
shawnschwartz/tinyvault:2025.10.0 # Specific version
shawnschwartz/tinyvault:latest # Always points to latest# Pull specific version
docker pull shawnschwartz/tinyvault:2025.10.0
# Deploy specific version to Cloud Run
gcloud run deploy cse-kacls \
--image shawnschwartz/tinyvault:2025.10.0 \
--region us-central1See CHANGELOG.md for version history.
- Multi-key support (different keys per user/department)
- Web UI for management
- Automated key rotation
Made with β€οΈ for the open source community
Save thousands on enterprise CSE. Encrypt everything.