-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsetup-template.sh
executable file
·426 lines (381 loc) · 14.3 KB
/
setup-template.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
#!/bin/bash
# ColourStream Template Setup Script
# This script helps initialize configuration files from templates
echo "ColourStream Template Setup"
echo "=========================="
echo
# Function to check if a command exists
command_exists() {
command -v "$1" >/dev/null 2>&1
}
# Check for required commands
echo "Checking dependencies..."
for cmd in docker docker-compose curl git openssl; do
if ! command_exists $cmd; then
echo "Error: $cmd is not installed."
echo "Please install $cmd and run this script again."
exit 1
fi
done
echo "All dependencies found."
echo
# Cleanup function to remove incorrect files with quotes in their names
cleanup_quoted_files() {
echo "Cleaning up any existing files with quotes in their names..."
# Find and delete files with quotes in their names ('' or "")
find . -name "*''" -type f -delete
find . -name '*""' -type f -delete
find . -name '*"' -type f -delete
# Delete specific known problematic files if they exist
files_to_check=(
"global.env''"
"docker-compose.yml''"
"backend/.env''"
"frontend/.env''"
"mirotalk/.env''"
)
for file in "${files_to_check[@]}"; do
if [ -f "$file" ]; then
rm -f "$file"
echo " Removed: $file"
fi
done
}
# Run cleanup before starting
cleanup_quoted_files
# Detect OS for sed in-place editing compatibility
if [[ "$OSTYPE" == "darwin"* ]]; then
# For macOS: use separate extension parameter
sed_inplace() {
sed -i "" "$@"
}
else
# For Linux and others
sed_inplace() {
sed -i "$@"
}
fi
# Function to check if environment is already configured
check_configured() {
if [ -f "global.env" ]; then
# Extract domain from global.env
if grep -q "DOMAIN=" global.env; then
configured_domain=$(grep "DOMAIN=" global.env | cut -d'=' -f2)
# Strip any 'live.colourstream.' or 'video.colourstream.' prefix
configured_domain=$(echo "$configured_domain" | sed -e 's/^live\.colourstream\.//' -e 's/^video\.colourstream\.//')
echo "Found existing configuration for domain: $configured_domain"
return 0
fi
fi
return 1
}
# Function to prompt for domain name
get_domain() {
read -p "Enter your domain name (e.g., example.com): " domain_name
if [ -z "$domain_name" ]; then
echo "Domain name cannot be empty. Please try again."
get_domain
fi
# Clean the domain name to ensure no newlines or extra spaces
domain_name=$(echo "$domain_name" | tr -d '\n\r' | xargs)
echo $domain_name
}
# Function to prompt for admin email
get_admin_email() {
read -p "Enter admin email address: " admin_email
if [ -z "$admin_email" ]; then
echo "Admin email cannot be empty. Please try again."
get_admin_email
fi
echo $admin_email
}
# Function to generate a random password
generate_password() {
openssl rand -hex 16
}
# Function to rotate secrets only
rotate_secrets() {
echo "Rotating secrets for existing installation..."
# Extract current domain and email from existing configuration
# DO NOT modify these during rotation
domain_name=$(grep "DOMAIN=" global.env | cut -d'=' -f2)
admin_email=$(grep "ADMIN_EMAIL=" global.env | cut -d'=' -f2)
echo "Preserving existing domain configuration:"
echo "Domain: $domain_name"
echo "Admin Email: $admin_email"
# Generate new passwords
db_password=$(generate_password)
jwt_key=$(generate_password)
jwt_secret=$(generate_password) # Generate separate JWT_SECRET
admin_password=$(generate_password)
admin_auth_secret=$(generate_password)
mirotalk_api_key=$(generate_password)
turn_password=$(generate_password)
ome_api_token=$(generate_password)
ome_webhook_secret=$(generate_password)
echo "Updating configuration files with new secrets..."
# Update global.env with new secrets
sed_inplace "s/DB_PASSWORD=.*/DB_PASSWORD=${db_password}/g" global.env
sed_inplace "s/POSTGRES_PASSWORD=.*/POSTGRES_PASSWORD=${db_password}/g" global.env
sed_inplace "s/JWT_KEY=.*/JWT_KEY=${jwt_key}/g" global.env
sed_inplace "s/JWT_SECRET=.*/JWT_SECRET=${jwt_secret}/g" global.env
sed_inplace "s/ADMIN_PASSWORD=.*/ADMIN_PASSWORD=${admin_password}/g" global.env
sed_inplace "s/ADMIN_AUTH_SECRET=.*/ADMIN_AUTH_SECRET=${admin_auth_secret}/g" global.env
sed_inplace "s/MIROTALK_API_KEY=.*/MIROTALK_API_KEY=${mirotalk_api_key}/g" global.env
sed_inplace "s/MIROTALK_API_KEY_SECRET=.*/MIROTALK_API_KEY_SECRET=${mirotalk_api_key}/g" global.env
sed_inplace "s/TURN_SERVER_CREDENTIAL=.*/TURN_SERVER_CREDENTIAL=${turn_password}/g" global.env
sed_inplace "s/OME_API_ACCESS_TOKEN=.*/OME_API_ACCESS_TOKEN=${ome_api_token}/g" global.env
sed_inplace "s/OME_WEBHOOK_SECRET=.*/OME_WEBHOOK_SECRET=${ome_webhook_secret}/g" global.env
echo "✅ Updated global.env"
# Update backend/.env with new secrets
if [ -f "backend/.env" ]; then
sed_inplace "s/DATABASE_URL=.*/DATABASE_URL=postgresql:\/\/colourstream:${db_password}@colourstream-postgres:5432\/colourstream/g" backend/.env
sed_inplace "s/JWT_KEY=.*/JWT_KEY=${jwt_key}/g" backend/.env
sed_inplace "s/JWT_SECRET=.*/JWT_SECRET=${jwt_secret}/g" backend/.env
sed_inplace "s/ADMIN_PASSWORD=.*/ADMIN_PASSWORD=${admin_password}/g" backend/.env
sed_inplace "s/ADMIN_AUTH_SECRET=.*/ADMIN_AUTH_SECRET=${admin_auth_secret}/g" backend/.env
sed_inplace "s/OME_API_ACCESS_TOKEN=.*/OME_API_ACCESS_TOKEN=${ome_api_token}/g" backend/.env
sed_inplace "s/OME_WEBHOOK_SECRET=.*/OME_WEBHOOK_SECRET=${ome_webhook_secret}/g" backend/.env
# Update HOST_USERS configuration
sed_inplace "s/HOST_USERS=.*/HOST_USERS=[{\"username\":\"admin\", \"password\":\"${admin_password}\"}]/g" backend/.env
echo "✅ Updated backend/.env"
else
echo "❌ backend/.env not found"
fi
# Update mirotalk/.env with new secrets
if [ -f "mirotalk/.env" ]; then
sed_inplace "s/TURN_SERVER_CREDENTIAL=.*/TURN_SERVER_CREDENTIAL=${turn_password}/g" mirotalk/.env
sed_inplace "s/API_KEY_SECRET=.*/API_KEY_SECRET=${mirotalk_api_key}/g" mirotalk/.env
sed_inplace "s/MIROTALK_API_KEY_SECRET=.*/MIROTALK_API_KEY_SECRET=${mirotalk_api_key}/g" mirotalk/.env
sed_inplace "s/JWT_KEY=.*/JWT_KEY=${jwt_key}/g" mirotalk/.env
sed_inplace "s/HOST_PASSWORD=.*/HOST_PASSWORD=${admin_password}/g" mirotalk/.env
# Update HOST_USERS configuration
sed_inplace "s/HOST_USERS=.*/HOST_USERS=[{\"username\":\"admin\", \"password\":\"${admin_password}\"}]/g" mirotalk/.env
echo "✅ Updated mirotalk/.env"
else
echo "❌ mirotalk/.env not found"
fi
# Update coturn config
if [ -f "coturn/turnserver.conf" ]; then
sed_inplace "s/user=colourstream:.*/user=colourstream:${turn_password}/g" coturn/turnserver.conf
echo "✅ Updated coturn/turnserver.conf"
else
echo "❌ coturn/turnserver.conf not found"
fi
# Update docker-compose.yml
if [ -f "docker-compose.yml" ]; then
sed_inplace "s/POSTGRES_PASSWORD: \"[^\"]*\"/POSTGRES_PASSWORD: \"${db_password}\"/g" docker-compose.yml
sed_inplace "s/DATABASE_URL: \"postgresql:\/\/colourstream:.*@colourstream-postgres/DATABASE_URL: \"postgresql:\/\/colourstream:${db_password}@colourstream-postgres/g" docker-compose.yml
sed_inplace "s/JWT_KEY: \"[^\"]*\"/JWT_KEY: \"${jwt_key}\"/g" docker-compose.yml
sed_inplace "s/JWT_SECRET: \"[^\"]*\"/JWT_SECRET: \"${jwt_secret}\"/g" docker-compose.yml
sed_inplace "s/ADMIN_AUTH_SECRET: \"[^\"]*\"/ADMIN_AUTH_SECRET: \"${admin_auth_secret}\"/g" docker-compose.yml
sed_inplace "s/OME_API_ACCESS_TOKEN: \"[^\"]*\"/OME_API_ACCESS_TOKEN: \"${ome_api_token}\"/g" docker-compose.yml
sed_inplace "s/OME_WEBHOOK_SECRET: \"[^\"]*\"/OME_WEBHOOK_SECRET: \"${ome_webhook_secret}\"/g" docker-compose.yml
sed_inplace "s/TURN_SERVER_CREDENTIAL: \"[^\"]*\"/TURN_SERVER_CREDENTIAL: \"${turn_password}\"/g" docker-compose.yml
sed_inplace "s/MIROTALK_API_KEY: \"[^\"]*\"/MIROTALK_API_KEY: \"${mirotalk_api_key}\"/g" docker-compose.yml
sed_inplace "s/MIROTALK_API_KEY_SECRET: \"[^\"]*\"/MIROTALK_API_KEY_SECRET: \"${mirotalk_api_key}\"/g" docker-compose.yml
# Add HOST_USERS configuration
sed_inplace "s/HOST_USERS: \"[^\"]*\"/HOST_USERS: \"[{\\\"username\\\":\\\"admin\\\", \\\"password\\\":\\\"${admin_password}\\\"}]\"/g" docker-compose.yml
echo "✅ Updated docker-compose.yml"
else
echo "❌ docker-compose.yml not found"
fi
# Create/update reference file for credentials
echo "Creating credentials reference file..."
cat > env.reference << EOL
# Generated Configuration - $(date)
# THIS IS A REFERENCE FILE ONLY - NOT USED BY THE APPLICATION
# Keep this file secure as it contains sensitive credentials
DOMAIN_NAME=${domain_name}
ADMIN_EMAIL=${admin_email}
DB_PASSWORD=${db_password}
JWT_KEY=${jwt_key}
JWT_SECRET=${jwt_secret}
ADMIN_PASSWORD=${admin_password}
ADMIN_AUTH_SECRET=${admin_auth_secret}
MIROTALK_API_KEY=${mirotalk_api_key}
TURN_PASSWORD=${turn_password}
OME_API_TOKEN=${ome_api_token}
OME_WEBHOOK_SECRET=${ome_webhook_secret}
# Existing URLs (preserved)
FRONTEND_URL=https://live.colourstream.${domain_name}
VIDEO_URL=https://video.colourstream.${domain_name}
EOL
chmod 600 env.reference
echo "✅ Created credentials reference file"
echo
echo "Secrets rotation complete!"
echo "New credentials have been saved to env.reference"
echo
echo "To apply these changes, restart the containers with:"
echo "docker-compose down && docker-compose up -d"
}
# Function to perform full setup
perform_full_setup() {
# Get user input
domain_name=$(get_domain)
admin_email=$(get_admin_email)
# Generate random passwords
db_password=$(generate_password)
jwt_key=$(generate_password)
jwt_secret=$(generate_password) # Generate separate JWT_SECRET
admin_password=$(generate_password)
admin_auth_secret=$(generate_password)
mirotalk_api_key=$(generate_password)
turn_password=$(generate_password)
ome_api_token=$(generate_password)
ome_webhook_secret=$(generate_password)
echo
echo "Creating configuration files..."
# Create global.env
cat > global.env << EOL
# Global Environment Variables
DOMAIN=${domain_name}
ADMIN_EMAIL=${admin_email}
DB_PASSWORD=${db_password}
POSTGRES_PASSWORD=${db_password}
JWT_KEY=${jwt_key}
JWT_SECRET=${jwt_secret}
ADMIN_PASSWORD=${admin_password}
ADMIN_AUTH_SECRET=${admin_auth_secret}
MIROTALK_API_KEY=${mirotalk_api_key}
MIROTALK_API_KEY_SECRET=${mirotalk_api_key}
TURN_SERVER_CREDENTIAL=${turn_password}
OME_API_ACCESS_TOKEN=${ome_api_token}
OME_WEBHOOK_SECRET=${ome_webhook_secret}
EOL
chmod 600 global.env
echo "✅ Created global.env"
# Create backend/.env
cat > backend/.env << EOL
# Backend Environment Variables
NODE_ENV=production
PORT=5001
DATABASE_URL=postgresql://colourstream:${db_password}@colourstream-postgres:5432/colourstream
JWT_KEY=${jwt_key}
JWT_SECRET=${jwt_secret}
ADMIN_AUTH_SECRET=${admin_auth_secret}
ADMIN_PASSWORD=${admin_password}
WEBAUTHN_RP_ID=live.colourstream.${domain_name}
WEBAUTHN_ORIGIN=https://live.colourstream.${domain_name}
DOMAIN=${domain_name}
VIDEO_DOMAIN=video.colourstream.${domain_name}
FRONTEND_URL=https://live.colourstream.${domain_name}
BASE_PATH=/api
OME_API_ACCESS_TOKEN=${ome_api_token}
OME_API_URL=http://origin:8081
OME_WEBHOOK_SECRET=${ome_webhook_secret}
EOL
chmod 600 backend/.env
echo "✅ Created backend/.env"
# Create mirotalk/.env
cat > mirotalk/.env << EOL
# MiroTalk Environment Variables
NODE_ENV=production
PROTOCOL=https
PORT=3000
JWT_KEY=${jwt_key}
HOST_PASSWORD=${admin_password}
TURN_SERVER_ENABLED=true
TURN_SERVER_HOST=turn.colourstream.${domain_name}
TURN_SERVER_PORT=3478
TURN_SERVER_USERNAME=colourstream
TURN_SERVER_CREDENTIAL=${turn_password}
API_KEY_SECRET=${mirotalk_api_key}
MIROTALK_API_KEY_SECRET=${mirotalk_api_key}
EOL
chmod 600 mirotalk/.env
echo "✅ Created mirotalk/.env"
# Create docker-compose.yml
cat > docker-compose.yml << EOL
version: '3.8'
services:
# ... existing services ...
backend:
environment:
- HOST_USERS=[{"username":"admin", "password":"${admin_password}"}]
# ... other environment variables ...
mirotalk:
environment:
- HOST_USERS=[{"username":"admin", "password":"${admin_password}"}]
# ... other environment variables ...
# ... rest of docker-compose.yml ...
EOL
chmod 600 docker-compose.yml
echo "✅ Created docker-compose.yml"
# Create/update reference file for credentials
echo "Creating credentials reference file..."
cat > env.reference << EOL
# Generated Configuration - $(date)
# THIS IS A REFERENCE FILE ONLY - NOT USED BY THE APPLICATION
# Keep this file secure as it contains sensitive credentials
DOMAIN_NAME=${domain_name}
ADMIN_EMAIL=${admin_email}
DB_PASSWORD=${db_password}
JWT_KEY=${jwt_key}
JWT_SECRET=${jwt_secret}
ADMIN_PASSWORD=${admin_password}
ADMIN_AUTH_SECRET=${admin_auth_secret}
MIROTALK_API_KEY=${mirotalk_api_key}
TURN_PASSWORD=${turn_password}
OME_API_TOKEN=${ome_api_token}
OME_WEBHOOK_SECRET=${ome_webhook_secret}
# URLs
FRONTEND_URL=https://live.colourstream.${domain_name}
VIDEO_URL=https://video.colourstream.${domain_name}
EOL
chmod 600 env.reference
echo "✅ Created credentials reference file"
# ... rest of perform_full_setup function ...
}
# Main script logic
if check_configured; then
echo
echo "This system appears to be already configured."
echo
echo "What would you like to do?"
echo "1) Rotate secrets only (keep existing domain and configuration)"
echo "2) Perform full setup (will overwrite existing configuration)"
echo "3) Exit without changes"
echo
read -p "Enter your choice (1-3): " choice
case $choice in
1)
rotate_secrets
;;
2)
echo "Proceeding with full setup. This will overwrite your existing configuration."
read -p "Are you sure you want to continue? (y/n): " confirm
if [[ $confirm == [yY] || $confirm == [yY][eE][sS] ]]; then
perform_full_setup
else
echo "Setup cancelled."
exit 0
fi
;;
3)
echo "Exiting without changes."
exit 0
;;
*)
echo "Invalid choice. Exiting."
exit 1
;;
esac
else
echo "No existing configuration found. Proceeding with full setup."
perform_full_setup
fi
echo
echo "Setup completed successfully!"
echo
echo "Next steps:"
echo "1. Set up DNS records:"
printf " - live.colourstream.%s -> Your server IP\n" "${domain_name}"
printf " - video.colourstream.%s -> Your server IP\n" "${domain_name}"
echo
echo "2. Start the application:"
echo " docker-compose up -d"
echo
echo "3. Login with the admin credentials found in env.reference"
echo " KEEP THIS FILE SECURE!"