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.

Environment Variables

Loading…

Environment Variables

Relevant source files

Purpose and Scope

This document provides a comprehensive reference for all environment variables used in the Docker MQTT Mosquitto with Cloudflare Tunnel system. It covers the .env file structure, the .env.sample template, and security practices for managing sensitive credentials.

For information about the Docker Compose configuration that consumes these variables, see docker-compose.yml. For the initial setup process of configuring environment variables, see Local Configuration. For version control practices related to secret management, see Version Control Best Practices.

Environment Variable System Overview

The system uses a file-based environment variable pattern where secrets are stored in a .env file that is explicitly excluded from version control. A template file, .env.sample, is committed to the repository to document the required variables without exposing actual values.

File Structure

project-root/
├── .env                  # Actual secrets (gitignored)
├── .env.sample           # Template (version controlled)
├── .gitignore           # Excludes .env
└── docker-compose.yml   # Consumes environment variables

Sources : .env.sample1 .gitignore1

Environment Variable File Relationship

Analysis : This diagram shows the critical separation between template and actual secrets. The .env.sample file serves as documentation in version control, while .env contains actual credentials and is explicitly excluded by .gitignore. Developers copy the template and populate it with real values obtained from the Cloudflare dashboard.

Sources : .env.sample1 .gitignore1

CLOUDFLARE_TUNNEL_TOKEN

The system uses a single environment variable for authentication and configuration.

Variable Specification

Variable NameRequiredTypeDescription
CLOUDFLARE_TUNNEL_TOKENYesString (JWT)Authentication token generated by Cloudflare Zero Trust dashboard for tunnel access

Sources : .env.sample1

Purpose and Function

The CLOUDFLARE_TUNNEL_TOKEN is a JSON Web Token (JWT) that contains:

  • Tunnel identification information
  • Authentication credentials
  • Routing configuration
  • Cryptographic signatures

This token authorizes the cloudflared container to establish an outbound connection to Cloudflare’s network and route traffic to the local Mosquitto broker.

Token Format

The token is a base64-encoded JWT string with the following characteristics:

  • Length: Approximately 500-800 characters
  • Format: eyJ... (standard JWT prefix)
  • Components: Header, payload, and signature concatenated with dots

Example from template :

CLOUDFLARE_TUNNEL_TOKEN=your_token

Sources : .env.sample1

Obtaining the Token

The token is generated through the Cloudflare Zero Trust dashboard during tunnel creation. See Cloudflare Tunnel Setup for detailed instructions. The token should be copied from the dashboard and placed in the .env file.

sequenceDiagram
    participant User as "User"
    participant Dashboard as "Cloudflare Dashboard"
    participant EnvSample as ".env.sample"
    participant EnvFile as ".env (local)"
    participant Compose as "docker-compose.yml"
    participant Container as "cloudflared container"
    participant Tunnel as "Cloudflare Tunnel Service"
    
    User->>Dashboard: 1. Create tunnel
    Dashboard-->>User: 2. Generate CLOUDFLARE_TUNNEL_TOKEN
    
    User->>EnvSample: 3. Read template
    EnvSample-->>User: CLOUDFLARE_TUNNEL_TOKEN=your_token
    
    User->>EnvFile: 4. Create .env file
    User->>EnvFile: 5. Paste actual token
    
    Note over Compose: docker-compose up
    
    Compose->>EnvFile: 6. Read environment variables
    EnvFile-->>Compose: CLOUDFLARE_TUNNEL_TOKEN=eyJh...
    
    Compose->>Container: 7. Start container with env var
    Container->>Container: 8. cloudflared tunnel run
    Container->>Tunnel: 9. Authenticate with token
    Tunnel-->>Container: 10. Tunnel established
    
    Note over Container,Tunnel: Persistent outbound connection\nmaintained for traffic routing

Token Lifecycle and Usage

Analysis : The token is generated once during tunnel creation and remains valid until the tunnel is deleted or the token is rotated. The token is read from .env at container startup and used by the cloudflared tunnel run command to authenticate with Cloudflare’s network.

Sources : .env.sample1

Security Architecture

graph LR
    subgraph "Files That Can Be Committed"
        SAMPLE[".env.sample\nTemplate only"]
README["README.md"]
COMPOSE["docker-compose.yml"]
MOSQUITTO["mosquitto.conf"]
GITIGNORE_FILE[".gitignore"]
end
    
    subgraph "Files That Must Not Be Committed"
        ENV[".env\nContains actual token"]
DATA["data/*\nMosquitto persistence"]
end
    
    subgraph ".gitignore Rules"
        RULE1["Line 1: .env"]
RULE2["Line 2: data/*"]
end
    
 
   RULE1 -.->|excludes| ENV
 
   RULE2 -.->|excludes| DATA
    
 
   SAMPLE -.->|safe to commit| README
 
   ENV -.->|blocked by gitignore| SAMPLE

The .gitignore Boundary

The .gitignore file establishes a security boundary that prevents accidental exposure of secrets to version control.

Analysis : The .gitignore file contains two critical rules. Line 1 excludes .env to prevent token exposure. Line 2 excludes data/* to prevent committing Mosquitto’s persistence data, which may contain message history or subscriber information.

Sources : .gitignore:1-2

File Contents and Security Model

.env.sample (Template File)

Located at .env.sample1 this file provides:

  • Documentation of required variables

  • Example structure (not functional values)

  • Onboarding guide for new developers

    CLOUDFLARE_TUNNEL_TOKEN=your_token

The value your_token is a placeholder and will not work for authentication. Developers must replace it with an actual token from the Cloudflare dashboard.

Security Properties :

  • Safe to commit to public repositories
  • Contains no sensitive information
  • Serves as self-documenting configuration reference

.env (Actual Secrets File)

Not present in the repository; created locally by developers. Contains:

  • Real CLOUDFLARE_TUNNEL_TOKEN value
  • Full JWT string with authentication credentials

Security Properties :

  • Excluded from version control via .gitignore1
  • Should have restrictive file permissions (chmod 600 .env)
  • Must never be shared publicly or committed to Git

Sources : .env.sample1 .gitignore1

graph TB
    subgraph "Filesystem"
        ENV_FILE[".env file"]
end
    
    subgraph "Docker Compose Process"
        COMPOSE_CMD["docker-compose up"]
COMPOSE_PARSER["YAML Parser"]
COMPOSE_ENGINE["Docker Engine API"]
end
    
    subgraph "docker-compose.yml"
        SERVICE_DEF["cloudflared service definition"]
ENV_REF["environment:\n - CLOUDFLARE_TUNNEL_TOKEN"]
end
    
    subgraph "Container Runtime"
        CONTAINER["cloudflared container"]
PROCESS["cloudflared tunnel run"]
ENV_VAR["CLOUDFLARE_TUNNEL_TOKEN\nenvironment variable"]
end
    
 
   ENV_FILE -->|1. read automatically| COMPOSE_CMD
 
   COMPOSE_CMD --> COMPOSE_PARSER
 
   COMPOSE_PARSER -->|2. parse service config| SERVICE_DEF
 
   SERVICE_DEF --> ENV_REF
 
   ENV_REF -->|3. resolve variable| ENV_FILE
 
   ENV_FILE -->|4. substitute value| COMPOSE_ENGINE
 
   COMPOSE_ENGINE -->|5. create container with env| CONTAINER
 
   CONTAINER -->|6. start process| PROCESS
 
   PROCESS -->|7. read env var| ENV_VAR

Integration with Docker Compose

The docker-compose.yml file consumes environment variables from the .env file automatically through Docker Compose’s built-in environment file support.

Environment Variable Injection Flow

Analysis : Docker Compose automatically loads the .env file from the project root directory. When it encounters environment variable references in docker-compose.yml, it substitutes values from the .env file before passing them to the Docker Engine. The cloudflared process can then access CLOUDFLARE_TUNNEL_TOKEN as a standard environment variable.

Sources : .env.sample1

graph LR
    subgraph "Environment Variables"
        TOKEN["CLOUDFLARE_TUNNEL_TOKEN"]
end
    
    subgraph "Containers"
        CFD["cloudflared\n✓ Has access"]
MOSQ["mosquitto\n✗ No access"]
end
    
 
   TOKEN -->|injected via environment| CFD
 
   TOKEN -.->|not available| MOSQ

Variable Scoping

The CLOUDFLARE_TUNNEL_TOKEN is only available to the cloudflared container. The mosquitto container does not have access to this variable, demonstrating principle of least privilege.

Sources : .env.sample1

Best Practices

Local Development

  1. Initial Setup :

  2. File Permissions :

Restricts read/write access to the file owner only.

  1. Verification : Before starting containers, verify the token is populated:

If this returns empty, the token has not been configured.

Production Deployment

For production environments, consider alternatives to file-based secrets:

MethodSecurityRotationAudit
.env fileLowManualNo
Docker secretsMediumManualLimited
HashiCorp VaultHighAutomatedYes
AWS Secrets ManagerHighAutomatedYes
Azure Key VaultHighAutomatedYes

Production deployments should:

  • Use secrets management systems instead of .env files
  • Implement automatic token rotation
  • Enable audit logging for secret access
  • Use read-only access where possible
graph TB
    subgraph "Common Mistakes (DO NOT DO)"
        COMMIT["❌ Committing .env to Git"]
HARDCODE["❌ Hardcoding token in docker-compose.yml"]
PUBLIC["❌ Posting token in issues/forums"]
SHARE["❌ Sharing .env file via email/chat"]
PERMISSIONS["❌ World-readable .env file"]
end
    
    subgraph "Correct Practices (DO THIS)"
        GITIGNORE_CHECK["✓ Verify .env in .gitignore"]
ENV_PATTERN["✓ Use environment variable pattern"]
ROTATE["✓ Rotate tokens regularly"]
RESTRICT["✓ Restrict file permissions"]
SECRETS_MGR["✓ Use secrets manager in production"]
end
    
 
   COMMIT -.->|leads to| TOKEN_LEAK["Token Exposure"]
HARDCODE -.->|leads to| TOKEN_LEAK
 
   PUBLIC -.->|leads to| TOKEN_LEAK
 
   SHARE -.->|leads to| TOKEN_LEAK
 
   PERMISSIONS -.->|leads to| TOKEN_LEAK
    
 
   TOKEN_LEAK -.->|enables| UNAUTHORIZED["Unauthorized Access"]

Token Rotation

The CLOUDFLARE_TUNNEL_TOKEN can be rotated by:

  1. Creating a new tunnel in the Cloudflare dashboard
  2. Updating the .env file with the new token
  3. Restarting containers: docker-compose restart cloudflared

Common Security Mistakes

Sources : .gitignore1

Troubleshooting

Token Not Found Error

Symptom : cloudflared container fails to start with error about missing token.

Diagnosis :

  1. Verify .env file exists in project root
  2. Check token variable name is exactly CLOUDFLARE_TUNNEL_TOKEN
  3. Ensure no extra spaces or quotes around the token value

Solution : Create or correct the .env file using .env.sample1 as template.

Token Authentication Failed

Symptom : cloudflared container starts but fails to establish tunnel.

Diagnosis :

  1. Token may be invalid or expired
  2. Token may be from a different tunnel
  3. Tunnel may have been deleted in Cloudflare dashboard

Solution : Generate new token from Cloudflare dashboard and update .env file.

.env File Accidentally Committed

Symptom : .env file appears in Git history.

Immediate Actions :

  1. Rotate token immediately in Cloudflare dashboard
  2. Remove file from Git history using git filter-branch or BFG Repo-Cleaner
  3. Update .env with new token
  4. Verify .gitignore1 contains .env

Environment Variable Reference Table

VariableTypeRequiredDefaultContainerUsage
CLOUDFLARE_TUNNEL_TOKENString (JWT)YesNonecloudflaredAuthenticates tunnel connection to Cloudflare network

Sources : .env.sample1


Sources : .env.sample1 .gitignore:1-2

Dismiss

Refresh this wiki

Enter email to refresh