Bjo53 commited on
Commit
729deb0
·
verified ·
1 Parent(s): 707eda6

Update startup.sh for persistence

Browse files
Files changed (1) hide show
  1. startup.sh +78 -24
startup.sh CHANGED
@@ -1,32 +1,26 @@
1
  #!/bin/bash
2
  echo "===== Startup $(date) ====="
3
 
4
- # Security: Set restrictive permissions
5
  umask 077
6
 
7
- # Install huggingface_hub
8
  pip3 install --no-cache-dir -q huggingface_hub==0.23.0 --break-system-packages 2>/dev/null
9
 
10
- # Install Node.js
11
  if ! command -v node &> /dev/null; then
12
  echo "[Install] Node.js..."
13
  curl -fsSL https://deb.nodesource.com/setup_20.x | bash - 2>/dev/null
14
  apt-get install -y nodejs 2>/dev/null
15
  fi
16
 
17
- # Install Claude CLI
18
  echo "[Install] Claude CLI..."
19
  npm install -g @anthropic-ai/claude-code 2>/dev/null
20
 
21
- # Install Codex CLI
22
  echo "[Install] Codex CLI..."
23
  npm install -g @openai/codex 2>/dev/null
24
 
25
- # Create secure storage
26
- mkdir -p /persistent/.secrets
27
  chmod 700 /persistent/.secrets
28
 
29
- # Restore from dataset (encrypted)
30
  if [ -n "$HF_TOKEN" ] && [ -n "$HF_USERNAME" ]; then
31
  echo "[Storage] Restoring from dataset..."
32
  python3 -c "
@@ -36,37 +30,76 @@ token = os.environ.get('HF_TOKEN')
36
  username = os.environ.get('HF_USERNAME')
37
  repo_id = f'{username}/vps-storage'
38
  try:
39
- snapshot_download(repo_id=repo_id, repo_type='dataset', local_dir='/persistent', token=token, ignore_patterns=['.gitattributes','README.md'])
40
  print('[Storage] Restored!')
41
  except: print('[Storage] Fresh start')
42
  " 2>/dev/null
43
  fi
44
 
45
- # Secure backup (only backs up code, not secrets)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
  python3 -c "
47
- import os, time, threading, hashlib
48
- def secure_backup():
49
  while True:
50
- time.sleep(300)
51
  token = os.environ.get('HF_TOKEN')
52
  username = os.environ.get('HF_USERNAME')
53
  if token and username:
54
  try:
55
  from huggingface_hub import HfApi
56
  api = HfApi(token=token)
57
- # Only upload code files, skip secrets
58
  api.upload_folder(
59
  folder_path='/persistent',
60
  repo_id=f'{username}/vps-storage',
61
  repo_type='dataset',
62
- ignore_patterns=['.secrets/', '*.key', '*.pem', '.env'],
63
- commit_message='secure-backup'
 
64
  )
65
  except: pass
66
- threading.Thread(target=secure_backup, daemon=True).start()
67
  " &
68
 
69
- # Keep-alive ping (human-like)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70
  python3 -c "
71
  import os, time, random, threading, requests
72
  def ping():
@@ -74,14 +107,35 @@ def ping():
74
  try:
75
  host = os.environ.get('SPACE_HOST','')
76
  if host:
77
- headers = {
78
- 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
79
- 'Accept': 'text/html,application/xhtml+xml',
80
- }
81
- requests.get(f'https://{host}/', headers=headers, timeout=10)
82
  except: pass
83
- time.sleep(random.randint(900, 3600))
84
  threading.Thread(target=ping, daemon=True).start()
85
  " &
86
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
  exec uvicorn app:app --host 0.0.0.0 --port 7860 --ws websockets --proxy-headers --forwarded-allow-ips="*"
 
1
  #!/bin/bash
2
  echo "===== Startup $(date) ====="
3
 
 
4
  umask 077
5
 
 
6
  pip3 install --no-cache-dir -q huggingface_hub==0.23.0 --break-system-packages 2>/dev/null
7
 
 
8
  if ! command -v node &> /dev/null; then
9
  echo "[Install] Node.js..."
10
  curl -fsSL https://deb.nodesource.com/setup_20.x | bash - 2>/dev/null
11
  apt-get install -y nodejs 2>/dev/null
12
  fi
13
 
 
14
  echo "[Install] Claude CLI..."
15
  npm install -g @anthropic-ai/claude-code 2>/dev/null
16
 
 
17
  echo "[Install] Codex CLI..."
18
  npm install -g @openai/codex 2>/dev/null
19
 
20
+ mkdir -p /persistent/.secrets /persistent/sessions
 
21
  chmod 700 /persistent/.secrets
22
 
23
+ # Restore from dataset
24
  if [ -n "$HF_TOKEN" ] && [ -n "$HF_USERNAME" ]; then
25
  echo "[Storage] Restoring from dataset..."
26
  python3 -c "
 
30
  username = os.environ.get('HF_USERNAME')
31
  repo_id = f'{username}/vps-storage'
32
  try:
33
+ snapshot_download(repo_id=repo_id, repo_type='dataset', local_dir='/persistent', token=token, ignore_patterns=['.gitattributes','README.md','.git/*'])
34
  print('[Storage] Restored!')
35
  except: print('[Storage] Fresh start')
36
  " 2>/dev/null
37
  fi
38
 
39
+ # Reinstall packages
40
+ if [ -s /persistent/installed_packages.txt ]; then
41
+ echo "[Packages] Reinstalling tracked packages..."
42
+ while IFS= read -r pkg; do
43
+ [ -z "$pkg" ] && continue
44
+ if [[ "$pkg" == apt:* ]]; then
45
+ apt_pkg="${pkg#apt:}"
46
+ apt-get install -y -qq "$apt_pkg" 2>/dev/null
47
+ else
48
+ pip3 install -q "$pkg" --break-system-packages 2>/dev/null
49
+ fi
50
+ done < /persistent/installed_packages.txt
51
+ echo "[Packages] Done!"
52
+ fi
53
+
54
+ # Auto-save every 3 minutes
55
  python3 -c "
56
+ import os, time, threading
57
+ def auto_save():
58
  while True:
59
+ time.sleep(180)
60
  token = os.environ.get('HF_TOKEN')
61
  username = os.environ.get('HF_USERNAME')
62
  if token and username:
63
  try:
64
  from huggingface_hub import HfApi
65
  api = HfApi(token=token)
 
66
  api.upload_folder(
67
  folder_path='/persistent',
68
  repo_id=f'{username}/vps-storage',
69
  repo_type='dataset',
70
+ token=token,
71
+ commit_message='auto-save',
72
+ ignore_patterns=['.secrets/', '*.key', '*.pem', '.env', '.git/*']
73
  )
74
  except: pass
75
+ threading.Thread(target=auto_save, daemon=True).start()
76
  " &
77
 
78
+ # Package tracker
79
+ python3 -c "
80
+ import os, time, json, threading
81
+ def watch_pkgs():
82
+ seen = set()
83
+ if os.path.exists('/persistent/installed_packages.txt'):
84
+ with open('/persistent/installed_packages.txt') as f:
85
+ seen = {l.strip() for l in f if l.strip()}
86
+ while True:
87
+ time.sleep(15)
88
+ try:
89
+ result = os.popen('pip3 list --format=json 2>/dev/null').read()
90
+ if result:
91
+ pkgs = json.loads(result)
92
+ for pkg in pkgs:
93
+ name = pkg.get('name','')
94
+ if name and name not in seen:
95
+ with open('/persistent/installed_packages.txt', 'a') as f:
96
+ f.write(name + '\n')
97
+ seen.add(name)
98
+ except: pass
99
+ threading.Thread(target=watch_pkgs, daemon=True).start()
100
+ " &
101
+
102
+ # Keep-alive ping
103
  python3 -c "
104
  import os, time, random, threading, requests
105
  def ping():
 
107
  try:
108
  host = os.environ.get('SPACE_HOST','')
109
  if host:
110
+ requests.get(f'https://{host}/', headers={'User-Agent': 'Mozilla/5.0'}, timeout=10)
 
 
 
 
111
  except: pass
112
+ time.sleep(random.randint(600, 1800))
113
  threading.Thread(target=ping, daemon=True).start()
114
  " &
115
 
116
+ # Bashrc for persistent env
117
+ cat > /root/.bashrc << 'EOF'
118
+ export HISTFILE=/persistent/.bash_history
119
+ export HISTSIZE=10000
120
+ export HISTFILESIZE=20000
121
+ export HISTCONTROL=ignoredups:erasedups
122
+ shopt -s histappend
123
+ alias pip='pip3'
124
+ alias install='track_pkg'
125
+ track_pkg() {
126
+ pip3 install "$@"
127
+ pkg_name=$(echo "$@" | awk '{print $1}' | sed 's/[^a-zA-Z0-9_-]//g')
128
+ if [ -n "$pkg_name" ] && ! grep -q "^${pkg_name}$" /persistent/installed_packages.txt 2>/dev/null; then
129
+ echo "$pkg_name" >> /persistent/installed_packages.txt
130
+ echo "[Tracking] Added: $pkg_name"
131
+ fi
132
+ }
133
+ EOF
134
+
135
+ cat > /root/.profile << 'EOF'
136
+ if [ -f /root/.bashrc ]; then . /root/.bashrc; fi
137
+ EOF
138
+
139
+ echo "[Startup] Ready!"
140
+
141
  exec uvicorn app:app --host 0.0.0.0 --port 7860 --ws websockets --proxy-headers --forwarded-allow-ips="*"