This documentation is part of the "Projects with Books" initiative at zenOSmosis.
The source code for this project is available on GitHub.
Version Control Practices
Relevant source files
Purpose and Scope
This document explains version control practices for the Docker MQTT Mosquitto Cloudflare Tunnel project, including what files are tracked in Git, what files are explicitly excluded, and best practices for managing secrets and runtime data. This covers the .gitignore configuration and the template-based secret management pattern using .env.sample.
For information about setting up the environment variables themselves, see Environment Variables. For deployment workflows and CI/CD processes, see CI/CD Pipeline.
Version Control Strategy
The project follows a strict separation between configuration templates (which are version controlled) and sensitive data or runtime artifacts (which are not). This ensures that the repository can be safely shared publicly while protecting secrets and avoiding repository bloat from generated files.
Version Controlled Files
The following categories of files are tracked in Git:
| Category | Files | Purpose |
|---|---|---|
| Orchestration | docker-compose.yml | Service definitions and container orchestration |
| Configuration Templates | mosquitto.conf, .env.sample | Non-sensitive configuration and secret templates |
| Documentation | README.md, LICENSE | Project documentation and licensing |
| CI/CD | .github/workflows/ci.yml | Automated testing configuration |
| Version Control Config | .gitignore | Exclusion rules for sensitive/generated files |
These files define the system's structure and behavior without containing sensitive credentials or environment-specific data.
Sources: .gitignore:1-3 README.md, docker-compose.yml, mosquitto.conf, .env.sample
Excluded Files
The .gitignore:1-3 file explicitly excludes two categories of files:
.env
data/*
These exclusions serve distinct purposes:
| Excluded Pattern | Purpose | Rationale |
|---|---|---|
.env | Sensitive credentials | Contains CLOUDFLARE_TUNNEL_TOKEN and other secrets |
data/* | Runtime artifacts | Generated data, persistence files, and logs |
Sources: .gitignore:1-3
The .gitignore Configuration
Diagram: Version Control Boundaries Defined by .gitignore
The .gitignore file is minimal but critical, containing only two rules that protect the repository from two distinct risks: credential exposure and runtime data pollution.
Sources: .gitignore:1-3
Rule 1: Excluding .env (Line 1)
The first exclusion rule .gitignore1 prevents the .env file from being committed. This file contains the CLOUDFLARE_TUNNEL_TOKEN required by the cloudflared service to authenticate with Cloudflare's network.
Security Implications:
- The tunnel token grants access to route traffic through the configured Cloudflare Tunnel
- If committed, the token would be permanently in Git history even if later removed
- Public repositories would expose credentials to anyone who clones the repository
- Compromised tokens allow unauthorized parties to proxy traffic through the tunnel
Sources: .gitignore1 .env.sample1
Rule 2: Excluding data/* (Line 2)
The second exclusion rule .gitignore2 prevents the data/ directory and all its contents from being tracked. This directory is used by the mosquitto container for runtime data storage.
Rationale:
- Mosquitto may store persistence files (retained messages, subscription state) in
data/ - Runtime logs and temporary files accumulate during operation
- These files are environment-specific and vary between deployments
- Including them would cause constant merge conflicts in collaborative workflows
- Binary persistence files would unnecessarily increase repository size
Sources: .gitignore2 docker-compose.yml
Secret Management Pattern
Diagram: Secret Management Workflow Using .env.sample Template
The project uses a template-based approach to manage secrets. The .env.sample:1-3 file serves as a documented template that IS version controlled, while the actual .env file with real credentials is never committed.
The .env.sample Template
CLOUDFLARE_TUNNEL_TOKEN=your_token
The .env.sample1 file contains:
- Variable names required by the system
- Placeholder values (e.g.,
your_token) that clearly indicate replacement is needed - Comments or documentation (if present) explaining each variable's purpose
Sources: .env.sample:1-3
Developer Workflow
When a developer clones the repository, they must:
-
Copy the template:
-
Obtain actual credentials from the Cloudflare Zero Trust dashboard (see Cloudflare Tunnel Configuration)
-
Replace placeholders in
.envwith real values:CLOUDFLARE_TUNNEL_TOKEN=eyJhIjoiYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoifQ... -
Verify the file is ignored by Git:
This workflow ensures every developer can configure their environment while keeping credentials out of version control.
Sources: .env.sample:1-3 .gitignore1
File Classification Decision Tree
Diagram: Decision Tree for Version Control Classification
This decision tree helps determine whether a file should be committed, excluded, or committed as a template.
Sources: .gitignore:1-3 .env.sample:1-3
Best Practices for Contributors
Adding New Configuration Files
When introducing new configuration files to the project:
-
Evaluate for secrets: If the file will contain credentials, API keys, or tokens:
- Create a
.sampleor.exampleversion with placeholders - Commit the template file
- Add the actual filename to .gitignore:1-3
- Update documentation to explain required variables
- Create a
-
Evaluate for runtime data: If the file is generated during container operation:
- Add the file or directory pattern to .gitignore:1-3
- Document in README.md where the file comes from
- Consider whether users need to back up this data
-
Configuration without secrets: If the file defines behavior but has no sensitive data:
- Commit directly to the repository
- Consider whether different environments need different values (if so, use template pattern)
Sources: .gitignore:1-3 .env.sample:1-3
Verifying .gitignore Effectiveness
Before committing changes, verify that sensitive files are properly excluded:
If .env or data/* files appear in git status, the .gitignore:1-3 rules are not working correctly.
Sources: .gitignore:1-3
Handling Accidentally Committed Secrets
If secrets are accidentally committed:
- Do not simply delete the file and commit again (history still contains it)
- Immediately rotate the compromised credentials
- Remove from history using
git filter-branchorBFG Repo-Cleaner - Force push to rewrite remote history (only if repository is not shared)
- Update.gitignore:1-3 to prevent recurrence
For public repositories, assume any committed secret is compromised and rotate it immediately.
Sources: .gitignore1 .env.sample1
Git Workflow Integration
Clone and Setup
New contributors follow this workflow:
| Step | Command | Result |
|---|---|---|
| 1. Clone repository | git clone <repo-url> | Repository with templates only |
| 2. Copy env template | cp .env.sample .env | Local .env file created |
| 3. Configure secrets | Edit .env with real values | System ready to deploy |
| 4. Verify exclusion | git status | .env should not appear |
Sources: .env.sample:1-3 .gitignore1
Pull Requests and Code Review
When reviewing pull requests:
- Verify no
.envfiles are included in the diff - Check that new configuration files follow the template pattern
- Ensure .gitignore:1-3 is updated if new excludable patterns are introduced
- Confirm documentation is updated for new required environment variables
Sources: .gitignore:1-3
Branch Strategy
The main branch contains:
- All version-controlled configuration files
- The
.gitignoreexclusion rules - Template files like
.env.sample
Developers should never commit:
- The actual
.envfile (excluded by .gitignore1) - Contents of the
data/directory (excluded by .gitignore2) - Any other secrets or credentials
Sources: .gitignore:1-3
Relationship to CI/CD
The GitHub Actions CI workflow (see CI/CD Pipeline) runs without access to the .env file because:
- The CI environment does not require
CLOUDFLARE_TUNNEL_TOKEN(tests only verify Mosquitto startup) - The cloudflared service is not started during CI tests
- The docker-compose.yml is structured to allow testing individual services
This demonstrates proper separation of concerns: version-controlled configuration can be tested without requiring secrets.
Sources: .gitignore:1-3 .github/workflows/ci.yml
Summary
The version control strategy for this project achieves three goals:
- Security: Secrets remain local and never enter Git history (enforced by .gitignore1)
- Clarity: Templates provide clear documentation of required configuration (via .env.sample1)
- Clean repository: Runtime artifacts don't pollute version control (excluded by .gitignore2)
This approach enables safe public repository sharing while maintaining functional deployment instructions for all contributors.
Sources: .gitignore:1-3 .env.sample:1-3