# Using Separate Env Files Per Container This guide shows you how to use separate `.env` files for each bot container, making it easy to manage both shared and bot-specific settings. ## How It Works Docker Compose loads `env_file` entries in order. Later files override earlier ones: 1. **`.env.shared`** - Loaded first, contains common settings 2. **`.env.user1`, `.env.user2`, `.env.user3`** - Loaded after, can override shared settings This means: - ✅ Shared settings go in `.env.shared` (update once) - ✅ Bot-specific overrides go in `.env.user1`, `.env.user2`, etc. (only if needed) - ✅ Easy to edit (plain text files, no JSON) ## Quick Setup ### Step 1: Create Env Files Run the setup script: ```bash chmod +x env-files-setup.sh ./env-files-setup.sh ``` This creates: - `.env.shared` - Shared settings for all bots - `.env.user1` - Overrides for bot 1 (optional) - `.env.user2` - Overrides for bot 2 (optional) - `.env.user3` - Overrides for bot 3 (optional) ### Step 2: Edit `.env.shared` Edit `.env.shared` with your shared settings: ```bash # Shared configuration for all nanobot instances NANOBOT_PROVIDERS__OPENROUTER__API_KEY=sk-or-v1-your-actual-key NANOBOT_AGENTS__DEFAULTS__MODEL=anthropic/claude-opus-4-5 NANOBOT_AGENTS__DEFAULTS__TEMPERATURE=0.7 NANOBOT_AGENTS__DEFAULTS__MAX_TOKENS=8192 ``` ### Step 3: Edit Bot-Specific Files (Optional) If a bot needs different settings, edit its `.env.userX` file: **`.env.user1`** (example - override model for bot 1): ```bash # Override model for this bot only NANOBOT_AGENTS__DEFAULTS__MODEL=anthropic/claude-sonnet-4 ``` **`.env.user2`** (example - override temperature): ```bash # Override temperature for this bot only NANOBOT_AGENTS__DEFAULTS__TEMPERATURE=0.9 ``` **`.env.user3`** (example - leave empty to use all shared settings): ```bash # This bot uses all settings from .env.shared # No overrides needed ``` ### Step 4: Create Minimal Config Files Each bot still needs a minimal `config.json` with bot-specific channel settings: **`~/.nanobot-user1/config.json`**: ```json { "channels": { "telegram": { "enabled": true, "token": "BOT_TOKEN_FOR_USER1", "allowFrom": ["USER1_TELEGRAM_ID"] } } } ``` **`~/.nanobot-user2/config.json`**: ```json { "channels": { "telegram": { "enabled": true, "token": "BOT_TOKEN_FOR_USER2", "allowFrom": ["USER2_TELEGRAM_ID"] } } } ``` ### Step 5: Run with Docker Compose ```bash docker compose -f docker-compose.multi.env.yml up -d ``` ## File Structure ``` nanobot/ ├── .env.shared ← Shared settings (API keys, model, etc.) ├── .env.user1 ← Bot 1 overrides (optional) ├── .env.user2 ← Bot 2 overrides (optional) ├── .env.user3 ← Bot 3 overrides (optional) ├── docker-compose.multi.env.yml │ └── ~/.nanobot-user1/ └── config.json ← Bot 1 channel config (Telegram token, user ID) └── ~/.nanobot-user2/ └── config.json ← Bot 2 channel config └── ~/.nanobot-user3/ └── config.json ← Bot 3 channel config ``` ## Examples ### Example 1: All Bots Use Same Settings **`.env.shared`**: ```bash NANOBOT_PROVIDERS__OPENROUTER__API_KEY=sk-or-v1-xxx NANOBOT_AGENTS__DEFAULTS__MODEL=anthropic/claude-opus-4-5 ``` **`.env.user1`**, **`.env.user2`**, **`.env.user3`**: ```bash # Empty - all bots use shared settings ``` ### Example 2: One Bot Uses Different Model **`.env.shared`**: ```bash NANOBOT_PROVIDERS__OPENROUTER__API_KEY=sk-or-v1-xxx NANOBOT_AGENTS__DEFAULTS__MODEL=anthropic/claude-opus-4-5 ``` **`.env.user1`**: ```bash # Bot 1 uses a different model NANOBOT_AGENTS__DEFAULTS__MODEL=anthropic/claude-sonnet-4 ``` **`.env.user2`**, **`.env.user3`**: ```bash # Empty - use shared model ``` ### Example 3: One Bot Uses Different API Key **`.env.shared`**: ```bash NANOBOT_PROVIDERS__OPENROUTER__API_KEY=sk-or-v1-shared-key NANOBOT_AGENTS__DEFAULTS__MODEL=anthropic/claude-opus-4-5 ``` **`.env.user2`**: ```bash # Bot 2 uses its own API key NANOBOT_PROVIDERS__OPENROUTER__API_KEY=sk-or-v1-user2-key ``` ## Updating Settings ### Update Shared Settings Edit `.env.shared` and restart all containers: ```bash # Edit shared settings nano .env.shared # Restart all bots docker compose -f docker-compose.multi.env.yml restart ``` ### Update Bot-Specific Settings Edit the specific `.env.userX` file and restart that bot: ```bash # Edit bot 1's settings nano .env.user1 # Restart only bot 1 docker restart nanobot-user1 ``` ## Environment Variable Format Nanobot uses Pydantic's `BaseSettings` with: - Prefix: `NANOBOT_` - Nested delimiter: `__` (double underscore) Examples: - `NANOBOT_PROVIDERS__OPENROUTER__API_KEY` → `providers.openrouter.apiKey` - `NANOBOT_AGENTS__DEFAULTS__MODEL` → `agents.defaults.model` - `NANOBOT_AGENTS__DEFAULTS__TEMPERATURE` → `agents.defaults.temperature` ## Advantages ✅ **Easy to edit** - Plain text files, no JSON syntax ✅ **Clear separation** - Shared vs bot-specific settings ✅ **Flexible** - Override only what you need ✅ **Version control friendly** - Can commit `.env.shared`, ignore `.env.userX` if they contain secrets ✅ **No config.json editing** - Only edit env files for most changes ## Troubleshooting ### Settings Not Applied 1. Check if env files exist: ```bash ls -la .env.* ``` 2. Check what's loaded in container: ```bash docker exec nanobot-user1 env | grep NANOBOT ``` 3. Restart container after changes: ```bash docker restart nanobot-user1 ``` ### Override Not Working Remember: Later files override earlier ones. If `.env.user1` has a setting but it's not applied, check: - Is the variable name correct? (use `__` not `.`) - Did you restart the container? - Is the setting in `.env.shared` overriding it? (remove from `.env.shared` if you want bot-specific only)