krinya commited on
Commit
f4f2765
·
1 Parent(s): d913a3d

refactor: update SSH key variable name to SSH_PEM_CONTENT for consistency

Browse files
docs/HUGGINGFACE_DEPLOYMENT.md ADDED
@@ -0,0 +1,148 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Hugging Face Deployment Guide
2
+
3
+ This guide explains how to deploy your sales assistant application on Hugging Face Spaces with secure SSH key management.
4
+
5
+ ## Setting Up Secrets in Hugging Face
6
+
7
+ 1. **Go to your Hugging Face Space settings**
8
+ - Navigate to your space on Hugging Face
9
+ - Click on "Settings" tab
10
+ - Go to "Repository secrets"
11
+
12
+ 2. **Add the following secrets:**
13
+
14
+ ### Required Database Secrets
15
+ ```
16
+ SSH_HOSTNAME=your.ssh.hostname.com
17
+ SSH_PORT=22
18
+ SSH_USERNAME=your-ssh-username
19
+ SSH_PEM_CONTENT=-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEA...\n-----END RSA PRIVATE KEY-----
20
+ MYSQL_HOST=your.mysql.hostname.com
21
+ MYSQL_PORT=3306
22
+ MYSQL_USER=your-mysql-user
23
+ MYSQL_PASSWORD=your-mysql-password
24
+ MYSQL_DB=your-database-name
25
+ ```
26
+
27
+ ### Required API Keys
28
+ ```
29
+ OPENAI_API_KEY=your-openai-api-key
30
+ HUGGINGFACE_API_KEY=your-hf-api-key
31
+ TAVILY_API_KEY=your-tavily-api-key
32
+ BREVO_API_KEY=your-brevo-api-key
33
+ COMPANY_EMAIL=your-company@email.com
34
+ ```
35
+
36
+ ### Optional Configuration
37
+ ```
38
+ MODEL_NAME=gpt-5-mini
39
+ MODEL_PROVIDER=openai
40
+ LANGSMITH_API_KEY=your-langsmith-key
41
+ LANGSMITH_TRACING_V2=true
42
+ LANGSMITH_ENDPOINT=https://api.smith.langchain.com
43
+ LANGSMITH_PROJECT=your-project-name
44
+ ```
45
+
46
+ ## SSH PEM Content Format
47
+
48
+ When adding your SSH private key as `SSH_PEM_CONTENT`, use this format:
49
+
50
+ ```
51
+ -----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEA0dtZotnwrz2jVSz2X3cZ...\n-----END RSA PRIVATE KEY-----
52
+ ```
53
+
54
+ **Important Notes:**
55
+ - Replace actual line breaks with `\n`
56
+ - Don't include quotes around the content
57
+ - Keep the BEGIN/END lines intact
58
+ - Include the `\n` characters exactly as shown
59
+
60
+ ## How It Works
61
+
62
+ Our implementation now uses **paramiko directly** instead of temporary files:
63
+
64
+ ### ✅ Advantages of Current Implementation
65
+ - **No temporary files**: PEM content is parsed directly in memory
66
+ - **Hugging Face friendly**: Works seamlessly with HF secrets
67
+ - **More secure**: No files written to disk
68
+ - **Cloud native**: Perfect for containerized environments
69
+ - **Fallback support**: Still works with file-based keys if needed
70
+
71
+ ### 🔄 Process Flow
72
+ 1. **Load environment variables** from HF secrets
73
+ 2. **Parse PEM content** directly using paramiko
74
+ 3. **Create SSH tunnel** using the parsed key object
75
+ 4. **Connect to database** through the secure tunnel
76
+ 5. **Clean shutdown** with no temporary files to clean up
77
+
78
+ ## Testing Locally
79
+
80
+ To test your HF deployment locally:
81
+
82
+ 1. **Copy your secrets** to a local `.env` file (temporarily)
83
+ 2. **Run the test**: `uv run python test_files/db_test.py`
84
+ 3. **Verify output**: Look for "✅ Successfully created SSH key from PEM content"
85
+ 4. **Delete local .env**: Don't commit secrets to git!
86
+
87
+ ## Deployment Files for HF
88
+
89
+ Make sure your Hugging Face space includes:
90
+
91
+ - `app.py` (or your main application file)
92
+ - `requirements.txt` (or `pyproject.toml`)
93
+ - `README.md`
94
+
95
+ Example `app.py` for Gradio:
96
+ ```python
97
+ import gradio as gr
98
+ from src.sales_assistant.ui_dashboard.gradio_app import create_app
99
+
100
+ if __name__ == "__main__":
101
+ app = create_app()
102
+ app.launch()
103
+ ```
104
+
105
+ ## Troubleshooting
106
+
107
+ ### Common Issues:
108
+
109
+ 1. **"No SSH key available"**
110
+ - Check that `SSH_PEM_CONTENT` is properly set in HF secrets
111
+ - Verify the PEM format includes `\n` characters
112
+
113
+ 2. **"Could not parse PEM content"**
114
+ - Ensure the PEM content is properly formatted
115
+ - Check that the private key is valid
116
+
117
+ 3. **Connection timeout**
118
+ - Verify SSH hostname and port
119
+ - Check that the SSH server allows connections from HF infrastructure
120
+
121
+ 4. **MySQL connection failed**
122
+ - Verify MySQL credentials
123
+ - Check that MySQL server allows connections from your SSH server
124
+
125
+ ### Debug Mode
126
+
127
+ Add this to your app for debugging:
128
+ ```python
129
+ import os
130
+ print(f"SSH_PEM_CONTENT loaded: {bool(os.getenv('SSH_PEM_CONTENT'))}")
131
+ print(f"SSH_HOSTNAME: {os.getenv('SSH_HOSTNAME')}")
132
+ ```
133
+
134
+ ## Security Best Practices
135
+
136
+ 1. **Never commit secrets** to your git repository
137
+ 2. **Use HF secrets** for all sensitive information
138
+ 3. **Rotate SSH keys** periodically
139
+ 4. **Monitor access logs** on your SSH and database servers
140
+ 5. **Use strong passwords** for database accounts
141
+ 6. **Consider IP whitelisting** if possible
142
+
143
+ ## Performance Tips
144
+
145
+ 1. **Connection pooling**: The implementation reuses connections efficiently
146
+ 2. **Query optimization**: Use indexed columns for faster queries
147
+ 3. **Caching**: Consider caching frequently accessed data
148
+ 4. **Monitoring**: Set up monitoring for your database and SSH server
docs/SSH_KEY_MANAGEMENT.md ADDED
File without changes
scripts/setup_hf_secrets.py ADDED
File without changes
test_files/db_test.py CHANGED
@@ -4,7 +4,7 @@ import pandas as pd
4
 
5
  # Validate configuration
6
  required_vars = [
7
- 'SSH_HOSTNAME', 'SSH_USERNAME', 'SSH_PKEY_PATH',
8
  'MYSQL_HOST', 'MYSQL_USER', 'MYSQL_PASSWORD', 'MYSQL_DB'
9
  ]
10
  validate_config_vars = validate_config(required_vars)
 
4
 
5
  # Validate configuration
6
  required_vars = [
7
+ 'SSH_HOSTNAME', 'SSH_USERNAME', 'SSH_PEM_CONTENT',
8
  'MYSQL_HOST', 'MYSQL_USER', 'MYSQL_PASSWORD', 'MYSQL_DB'
9
  ]
10
  validate_config_vars = validate_config(required_vars)