.NET 9 background service that syncs local .env files with remote Git repositories automatically
10K+
A lightweight .NET 9 background service that automatically keeps your local .env files in sync with their corresponding versions hosted in remote Git repositories (e.g., GitHub).
.env files by comparing variable names with the remote version.env to the local file.env file before any update (.env.bak_TIMESTAMP)The service is configured entirely via a config.json file located in the application's root directory. This file defines which services to monitor, how often to check for updates, and general behavior settings.
| Field | Type | Description | Default |
|---|---|---|---|
checkInterval | int | Interval in seconds between each sync check | 3600 |
saveBackupFile | bool | If true, a .env.bak_TIMESTAMP backup is created before any update | true |
timezone | string | Timezone used for logging timestamps (e.g., UTC, America/New_York, Europe/Rome) | "UTC" |
services | array | List of service objects to monitor (see below) | [] |
logLevel | string | Logging verbosity level (Trace, Debug, Information, Warning, Error, Critical). For Information, Warning, and Critical, short forms are also accepted (info, warn, crit). | info |
Each entry in the services array represents a single .env file to keep in sync:
| Field | Type | Required | Description |
|---|---|---|---|
name | string | ✅ | A friendly name to identify the service in logs |
repositoryEnvUrl | string | ✅ | The URL pointing to the remote .env file in the Git repository |
localEnvPath | string | ✅ | The absolute path to the local .env file to keep in sync |
Note
Both standard GitHub URLs (`https://github.com/user/repo/blob/main/.env`) and raw URLs (`https://raw.githubusercontent.com/user/repo/refs/heads/main/.env`) are supported. Standard URLs are **automatically converted** to raw format at runtime.
Below is a complete config.json example that monitors three different services:
{
"services":
[
{
"name": "AuthService",
"repositoryEnvUrl": "https://raw.githubusercontent.com/myorg/auth-service/refs/heads/main/.env-sample",
"localEnvPath": "/app/envs/auth-service/.env"
},
{
"name": "PaymentGateway",
"repositoryEnvUrl": "https://github.com/myorg/payment-gateway/blob/main/.env-sample",
"localEnvPath": "/app/envs/payment-gateway/.env"
},
{
"name": "NotificationService",
"repositoryEnvUrl": "https://raw.githubusercontent.com/myorg/notifications/refs/heads/develop/.env-sample",
"localEnvPath": "/app/envs/notifications/.env"
}
],
"checkInterval": 1800,
"saveBackupFile": true,
"timezone": "Europe/Rome",
"logLevel": "info"
}
Important
When running inside Docker, the `localEnvPath` values must reference paths **inside the container**. These paths must be mapped to the actual host directories via Docker volumes. See the [Deployment](#-deployment) section for details.
The recommended way to deploy EnvAutoUpdater is via Docker Compose. Create a docker-compose.yml file:
services:
env-auto-updater:
image: krystall0/envautoupdater:latest
container_name: env-auto-updater
restart: unless-stopped
volumes:
# Mount the configuration file (read-only)
- ./config.json:/app/config.json:ro
# Mount the local .env directories for each monitored service.
# The container needs read/write access to update the .env files.
- /home/user/projects/auth-service:/app/envs/auth-service
- /home/user/projects/payment-gateway:/app/envs/payment-gateway
- /home/user/projects/notifications:/app/envs/notifications
Then, start the service:
docker-compose up -d
This will download the latest image, create the container, and start the EnvAutoUpdater service in detached mode. The logs can be viewed with:
docker-compose logs env-auto-updater -f
Ensure that the host directories (e.g., /home/user/projects/auth-service) exist and contain the .env files you want to monitor. The container will map these directories to /app/envs/... paths.
Caution
If a volume is not correctly mapped, the container will not be able to read or write the `.env` file. The service will log an error and skip that service until the next check cycle.
Tip
Mount `config.json` as **read-only** (`:ro`) since the service only reads it. Do **not** mount `.env` directories as read-only — the service needs write access to update them.
For development or testing, you can run the service directly on your machine (assuming .NET 9 SDK is installed):
git clone https://github.com/kRYstall9/EnvAutoUpdater.git
cd EnvAutoUpdater
Configure the service:
config.json to your needs.Run the service:
dotnet run
config.json at each iteration (the config can be changed without restarting the container; its updated content will be read at the next iteration)..env — reads the local file line by line via ReadLocalEnvFile..env — downloads the latest .env from the configured repository URL via ReadUpdatedEnvFileFromRepository.ReadEnvVariables to extract environment variable names (lines containing =).IsFileAlreadyUpdated if all remote variable names are already present in the local file.UpdateEnvFile:
.env.bak_TIMESTAMP copy before writing changes.checkInterval seconds, then repeats from step 1.=, or have spaces in the variable name are skipped.#) are recognized and their names are extracted by stripping the # prefix.Variables whose values span multiple lines (e.g., embedded JSON strings) are fully captured. The parser continues reading lines until it encounters an empty line, a comment, or a new variable assignment.
New variables found in the remote .env are appended commented out at the bottom of the local file, under a clearly identifiable marker section. This ensures your existing configuration is never overwritten — you review and uncomment the new variables manually.
If a variable already exists locally but its associated comments in the repository have changed, EnvAutoUpdater will:
saveBackupFile is enabled, a backup of the original .env file is saved as .env.bak_TIMESTAMP before any updates are applied. The timestamp format is yyyyMMddTHHmmss (e.g., .env.bak_20230101T120000).| Problem | Possible Cause | Solution |
|---|---|---|
| Service skips a service entry | localEnvPath points to a nonexistent file or unmapped volume | Verify the volume mapping in docker-compose.yml and ensure the .env file exists |
| No updates detected | Local file already contains all remote variables | Check logs for detailed comparison output |
| Permission denied errors | Docker container lacks write access to the mounted volume | Ensure the volume is not mounted as read-only (:ro) for .env directories |
| GitHub rate limiting | Too many requests to raw.githubusercontent.com | Increase checkInterval to reduce request frequency |
| Wrong timestamps in logs | Incorrect timezone configuration | Set timezone in config.json to your local timezone (e.g., Europe/Rome) |
This project is licensed under the MIT License. See the LICENSE file for details.
Content type
Image
Digest
sha256:253c9e8d0…
Size
39.2 MB
Last updated
7 months ago
docker pull krystall0/envautoupdater