Skill Tracer
Skills › Scientific Agent Skills › modal › secrets.md

secrets.md

136 lines · skills/modal/references/secrets.md at 5f2bc03

Open on GitHub
1# Modal Secrets
2
3Reviewed against SDK 1.6.0 and official [Secrets](https://modal.com/docs/guide/secrets)
4and [Secret API](https://modal.com/docs/reference/modal.Secret) documentation.
5The snippets are illustrative; no Secrets were created or credentials transmitted.
6

Modal Secrets

Reviewed against SDK 1.6.0 and official Secrets and Secret API documentation. The snippets are illustrative; no Secrets were created or credentials transmitted.

Raw lines 1 to 6
7## Overview
8
9Modal Secrets securely deliver credentials and sensitive data to functions as environment variables. Secrets are stored encrypted and only available to your workspace.

Overview

Modal Secrets securely deliver credentials and sensitive data to functions as environment variables. Secrets are stored encrypted and only available to your workspace.

Raw lines 7 to 10
11## Creating Secrets

Creating Secrets

Raw lines 11 to 12
13### Via CLI
15```bash
16# Create with key-value pairs
17modal secret create my-api-keys API_KEY=placeholder DB_PASSWORD=placeholder
19# Enter a value in an editor (keep real values out of shell history)
20modal secret create my-env-keys 'API_KEY=-'
22# List all secrets
23modal secret list
25# Delete a secret
26modal secret delete my-api-keys
27```
29`KEY=-` opens an editor so values need not appear in shell history. For programmatic
30use, read only the required key and use `Secret.from_dict`; avoid copying the full
31environment or an unrelated project `.env` into a remote workload.

Via CLI

# Create with key-value pairs
modal secret create my-api-keys API_KEY=placeholder DB_PASSWORD=placeholder

# Enter a value in an editor (keep real values out of shell history)
modal secret create my-env-keys 'API_KEY=-'

# List all secrets
modal secret list

# Delete a secret
modal secret delete my-api-keys

KEY=- opens an editor so values need not appear in shell history. For programmatic use, read only the required key and use Secret.from_dict; avoid copying the full environment or an unrelated project .env into a remote workload.

Raw lines 13 to 32
33### Via Dashboard
35Navigate to https://modal.com/secrets to create and manage secrets. Templates are available for common services (Postgres, MongoDB, Hugging Face, Weights & Biases, etc.).

Via Dashboard

Navigate to https://modal.com/secrets to create and manage secrets. Templates are available for common services (Postgres, MongoDB, Hugging Face, Weights & Biases, etc.).

Raw lines 33 to 36
37### Programmatic (Inline)
39```python
40# From a dictionary (useful for development)
41import os
42secret = modal.Secret.from_dict({"API_KEY": os.environ["API_KEY"]})
44# From a .env file
45secret = modal.Secret.from_dotenv()
47# From a named secret (created via CLI or dashboard)
48secret = modal.Secret.from_name("my-api-keys", required_keys=["API_KEY"])
49```

Programmatic (Inline)

# From a dictionary (useful for development)
import os
secret = modal.Secret.from_dict({"API_KEY": os.environ["API_KEY"]})

# From a .env file
secret = modal.Secret.from_dotenv()

# From a named secret (created via CLI or dashboard)
secret = modal.Secret.from_name("my-api-keys", required_keys=["API_KEY"])
Raw lines 37 to 50
51## Using Secrets in Functions

Using Secrets in Functions

Raw lines 51 to 52
53### Basic Usage
55```python
56@app.function(secrets=[modal.Secret.from_name("my-api-keys")])
57def call_api():
58 import os
59 import requests
60 api_key = os.environ["API_KEY"]
61 # Use the key
62 response = requests.get(url, headers={"Authorization": f"Bearer {api_key}"}, timeout=30)
63 response.raise_for_status()
64 return response.json()
65```

Basic Usage

@app.function(secrets=[modal.Secret.from_name("my-api-keys")])
def call_api():
    import os
    import requests
    api_key = os.environ["API_KEY"]
    # Use the key
    response = requests.get(url, headers={"Authorization": f"Bearer {api_key}"}, timeout=30)
    response.raise_for_status()
    return response.json()
Raw lines 53 to 66
67### Multiple Secrets
69```python
70@app.function(secrets=[
71 modal.Secret.from_name("openai-keys"),
72 modal.Secret.from_name("database-creds"),
73])
74def process():
75 import os
76 openai_key = os.environ["OPENAI_API_KEY"]
77 db_url = os.environ["DATABASE_URL"]
78 ...
79```
81Secrets are applied in order — if two secrets define the same key, the later one wins.

Multiple Secrets

@app.function(secrets=[
    modal.Secret.from_name("openai-keys"),
    modal.Secret.from_name("database-creds"),
])
def process():
    import os
    openai_key = os.environ["OPENAI_API_KEY"]
    db_url = os.environ["DATABASE_URL"]
    ...

Secrets are applied in order — if two secrets define the same key, the later one wins.

Raw lines 67 to 82
83### With Classes
85```python
86@app.cls(secrets=[modal.Secret.from_name("huggingface")])
87class ModelService:
88 @modal.enter()
89 def load(self):
90 import os
91 token = os.environ["HF_TOKEN"]
92 self.model = AutoModel.from_pretrained("model-name", token=token)
93```

With Classes

@app.cls(secrets=[modal.Secret.from_name("huggingface")])
class ModelService:
    @modal.enter()
    def load(self):
        import os
        token = os.environ["HF_TOKEN"]
        self.model = AutoModel.from_pretrained("model-name", token=token)
Raw lines 83 to 94
95### From .env File
97```python
98# Searches upward from the current working directory; install python-dotenv locally.
99@app.function(secrets=[modal.Secret.from_dotenv()])
100def local_dev():
101 import os
102 api_key = os.environ["API_KEY"]
103```
105`Secret.from_dotenv(path="./workload-config", filename=".env")` sets the search starting
106directory, but still searches parent directories. Verify the intended file exists.
107It reads all entries in the discovered file, so keep only intended remote credentials
108there. Modal platform tokens (`MODAL_TOKEN_*`) normally belong in the client profile,
109not in a workload Secret.
111The `.env` file format (placeholder values):
113```dotenv
114API_KEY=sk-xxx
115DATABASE_URL=postgres://user:pass@host/db
116DEBUG=false
117```

From .env File

# Searches upward from the current working directory; install python-dotenv locally.
@app.function(secrets=[modal.Secret.from_dotenv()])
def local_dev():
    import os
    api_key = os.environ["API_KEY"]

Secret.from_dotenv(path="./workload-config", filename=".env") sets the search starting directory, but still searches parent directories. Verify the intended file exists. It reads all entries in the discovered file, so keep only intended remote credentials there. Modal platform tokens (MODAL_TOKEN_*) normally belong in the client profile, not in a workload Secret.

The .env file format (placeholder values):

API_KEY=sk-xxx
DATABASE_URL=postgres://user:pass@host/db
DEBUG=false
Raw lines 95 to 118
119## Common Secret Templates
121| Service | Typical Keys |
122|---------|-------------|
123| OpenAI | `OPENAI_API_KEY` |
124| Hugging Face | `HF_TOKEN` |
125| AWS | `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY` |
126| Postgres | `PGHOST`, `PGPORT`, `PGUSER`, `PGPASSWORD`, `PGDATABASE` |
127| Weights & Biases | `WANDB_API_KEY` |
128| GitHub | `GITHUB_TOKEN` |

Common Secret Templates

ServiceTypical Keys
OpenAIOPENAI_API_KEY
Hugging FaceHF_TOKEN
AWSAWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY
PostgresPGHOST, PGPORT, PGUSER, PGPASSWORD, PGDATABASE
Weights & BiasesWANDB_API_KEY
GitHubGITHUB_TOKEN
Raw lines 119 to 129
130## Security Notes
132- Secrets are encrypted at rest and in transit
133- Only accessible to functions in your workspace
134- Never log or print secret values
135- Use `.from_name()` in production (not `.from_dict()`)
136- Rotate secrets regularly via the dashboard or CLI

Security Notes

  • Secrets are encrypted at rest and in transit
  • Only accessible to functions in your workspace
  • Never log or print secret values
  • Use .from_name() in production (not .from_dict())
  • Rotate secrets regularly via the dashboard or CLI
Raw lines 130 to 136