File size: 3,440 Bytes
f65541c
6bff870
e9e0a4f
 
6bff870
e9e0a4f
 
 
6bff870
 
 
e9e0a4f
6bff870
 
 
 
 
 
 
 
 
 
 
e9e0a4f
6bff870
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e9e0a4f
 
6bff870
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e9e0a4f
 
6bff870
 
 
 
 
 
 
 
 
 
 
e9e0a4f
6bff870
e9e0a4f
 
6bff870
c0ec0de
e9e0a4f
6bff870
 
 
 
 
 
 
e9e0a4f
6bff870
 
e9e0a4f
6bff870
 
b9a88a9
 
 
 
 
 
 
e9e0a4f
6bff870
 
 
 
 
e9e0a4f
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
FROM decolua/9router:latest

# 1. Switch to root to install system packages
USER root

# 2. Install Python for the backup script
RUN apk add --no-cache python3 py3-pip tar \
    && pip3 install --break-system-packages --no-cache-dir huggingface_hub

WORKDIR /app

# 3. Create the Python sync script
RUN cat > /app/sync.py <<'PY'
import os
import tarfile
import time
import sys
from pathlib import Path
from huggingface_hub import HfApi, hf_hub_download

REPO_ID = os.environ.get("DATASET_REPO")
TOKEN = os.environ.get("HF_TOKEN")
BACKUP_FILE = "/tmp/9router_backup.tar.gz"
DATA_DIR = Path("/app/data")

def safe_extract(tar, path):
    base = Path(path).resolve()
    for member in tar.getmembers():
        target = (base / member.name).resolve()
        if not str(target).startswith(str(base)):
            raise RuntimeError(f"Unsafe tar member: {member.name}")
    tar.extractall(path)

def upload():
    if not REPO_ID or not TOKEN:
        print(">>> [Sync] DATASET_REPO or HF_TOKEN not configured. Skipping backup.")
        return
    if not DATA_DIR.exists():
        print(">>> [Sync] Data directory does not exist. Skipping backup.")
        return
    try:
        with tarfile.open(BACKUP_FILE, "w:gz") as tar:
            # We pack the /app/data folder as 'data'
            tar.add(str(DATA_DIR), arcname="data")
        HfApi(token=TOKEN).upload_file(
            path_or_fileobj=BACKUP_FILE,
            path_in_repo="9router_backup.tar.gz",
            repo_id=REPO_ID,
            repo_type="dataset",
        )
        print(f">>> [Sync] Backup successful: {time.strftime('%Y-%m-%d %H:%M:%S')}", flush=True)
    except Exception as e:
        print(f">>> [Sync] Backup failed: {e}", flush=True)

def download():
    if not REPO_ID or not TOKEN:
        print(">>> [Sync] DATASET_REPO or HF_TOKEN not configured. Skipping restore.")
        return
    try:
        print(">>> [Sync] Downloading data from Dataset...", flush=True)
        path = hf_hub_download(
            repo_id=REPO_ID,
            filename="9router_backup.tar.gz",
            repo_type="dataset",
            token=TOKEN,
        )
        with tarfile.open(path, "r:gz") as tar:
            # Extracting into /app will perfectly place it at /app/data
            safe_extract(tar, "/app")
        print(">>> [Sync] Data restore successful.", flush=True)
    except Exception as e:
        print(f">>> [Sync] Skipping restore (might be first run): {e}", flush=True)

if __name__ == "__main__":
    if len(sys.argv) > 1 and sys.argv[1] == "upload":
        upload()
    elif len(sys.argv) > 1 and sys.argv[1] == "download":
        download()
PY

# 4. Create the startup shell script
RUN cat > /app/run.sh <<'SH'
#!/bin/sh
set -e

echo '=== 0. Resetting Local Data ==='
mkdir -p /app/data

echo '=== 1. Restoring Data ==='
python3 /app/sync.py download

echo '=== 2. Starting Scheduled Backup (Every 10 minutes) ==='
(while true; do sleep 600; python3 /app/sync.py upload; done) &

echo '=== 3. Starting 9router ==='
export PORT=7860
export HOSTNAME=0.0.0.0
export DATA_DIR=/app/data
export NEXT_PUBLIC_BASE_URL="https://${SPACE_HOST:-otnansirk-9router.hf.space}"

echo '=== Checking 9router files ==='
pwd
ls -la
node -e "console.log(require('./package.json').version)" || true
cat package.json | grep version || true

echo '=== 3. Starting 9router ==='
exec node server.js
SH

RUN chmod +x /app/run.sh

EXPOSE 7860
CMD ["/bin/sh", "/app/run.sh"]