Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

GitHub

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:

CategoryFilesPurpose
Orchestrationdocker-compose.ymlService definitions and container orchestration
Configuration Templatesmosquitto.conf, .env.sampleNon-sensitive configuration and secret templates
DocumentationREADME.md, LICENSEProject documentation and licensing
CI/CD.github/workflows/ci.ymlAutomated testing configuration
Version Control Config.gitignoreExclusion 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 PatternPurposeRationale
.envSensitive credentialsContains CLOUDFLARE_TUNNEL_TOKEN and other secrets
data/*Runtime artifactsGenerated 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:

  1. Copy the template:

  2. Obtain actual credentials from the Cloudflare Zero Trust dashboard (see Cloudflare Tunnel Configuration)

  3. Replace placeholders in .env with real values:

    CLOUDFLARE_TUNNEL_TOKEN=eyJhIjoiYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoifQ...
    
  4. 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:

  1. Evaluate for secrets: If the file will contain credentials, API keys, or tokens:

    • Create a .sample or .example version with placeholders
    • Commit the template file
    • Add the actual filename to .gitignore:1-3
    • Update documentation to explain required variables
  2. 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
  3. 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:

  1. Do not simply delete the file and commit again (history still contains it)
  2. Immediately rotate the compromised credentials
  3. Remove from history using git filter-branch or BFG Repo-Cleaner
  4. Force push to rewrite remote history (only if repository is not shared)
  5. 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:

StepCommandResult
1. Clone repositorygit clone <repo-url>Repository with templates only
2. Copy env templatecp .env.sample .envLocal .env file created
3. Configure secretsEdit .env with real valuesSystem ready to deploy
4. Verify exclusiongit status.env should not appear

Sources: .env.sample:1-3 .gitignore1

Pull Requests and Code Review

When reviewing pull requests:

  • Verify no .env files 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 .gitignore exclusion rules
  • Template files like .env.sample

Developers should never commit:

  • The actual .env file (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:

  1. The CI environment does not require CLOUDFLARE_TUNNEL_TOKEN (tests only verify Mosquitto startup)
  2. The cloudflared service is not started during CI tests
  3. 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:

  1. Security: Secrets remain local and never enter Git history (enforced by .gitignore1)
  2. Clarity: Templates provide clear documentation of required configuration (via .env.sample1)
  3. 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