# התקנה

> התקנת Nodaro באירוח עצמי שלב אחר שלב: שכפול מאגר הקוד, הגדרת ‎.env, סודות, מיגרציות ואחסון אובייקטים, הפעלת המערך, התחברות והקשחה.

Source: https://nodaro.ai/he/docs/self-hosting/install

בדף הזה **מתקינים** את מהדורת Community שלב אחר שלב, עם הסיבות שמאחורי כל שלב. אלה אותם שלבים כמו בדף [התחלה מהירה](https://nodaro.ai/docs/self-hosting/quickstart), ובנוסף שירותים מנוהלים, סודות, אחסון והקשחה. במערך השירותים המובנה של Compose, רוב השלבים לא דורשים שום פעולה: קראו אותם כדי לדעת מה קורה ומה לשנות בהמשך.

## 1. שכפול והגדרה
```bash
git clone https://github.com/nodaroai/app.nodaro.ai.git nodaro
cd nodaro
```

במערך השירותים של Compose למהדורת Community, הקובץ `.env` אופציונלי. קובץ ה-Compose כולל את Supabase, את MinIO ואת Redis עם ברירות מחדל שעובדות. צרו `.env` רק כדי להוסיף מפתחות ספק, לשנות את הכתובת הציבורית, או לכוון את Nodaro לשירותים מנוהלים משלכם.

כדי ליצור קובץ כזה, העתיקו את קובץ הדוגמה שהוכן למערך השירותים של Compose:

```bash
cp .env.community.example .env
```

**אל תעתיקו את ‎.env.example למערך השירותים של Compose:** 
הקובץ `.env.example` הוא קובץ העזר להתקנות מחוץ למערך השירותים של Compose. ערכי הדוגמה שבו, כגון `SUPABASE_URL=https://YOUR-PROJECT.supabase.co`, מחליפים את ברירות המחדל של Compose ושוברים את מסד הנתונים המובנה.

הערכים שמגדירים בדרך כלל:

```bash
PUBLIC_URL=http://localhost:3000        # your install's public address

# Only with a managed Supabase project instead of the bundled one:
SUPABASE_URL=https://YOUR-PROJECT.supabase.co
SUPABASE_SERVICE_ROLE_KEY=eyJ...
SUPABASE_ANON_KEY=eyJ...

# At least one model provider:
KIE_API_KEY=
REPLICATE_API_TOKEN=
ANTHROPIC_API_KEY=
ELEVENLABS_API_KEY=
```

קובץ ה-Compose מעביר לאפליקציה רשימה קבועה של משתנים. את המשתנים שלא מופיעים ברשימה הזו צריך להוסיף לשירות `nodaro` בקובץ `docker-compose.community.yml`. הדף [תצורה](https://nodaro.ai/docs/self-hosting/configuration) מפרט את כל המשתנים ומציין אילו מהם אפשר להגדיר ב-`.env`.

## 2. יצירת הסודות הפנימיים
Nodaro משתמש בשני סודות משלו:

| משתנה | מה הוא עושה |
| --- | --- |
| `INTERNAL_ORCHESTRATOR_SECRET` | מאמת את ה-orchestrator מול ה-API בתוך קונטיינר של Nodaro. לפחות 32 תווים. |
| `NODARO_ENCRYPTION_KEY` | מפתח הקסדצימלי באורך 64 תווים שמצפין פרטי גישה שמורים: מפתחות ספק שהודבקו ב-`/setup`, אסימוני התחברות לרשתות חברתיות, ופרטי הגישה ל-HTTP שמשתמשים שומרים ברכיב [פלט Webhook](https://nodaro.ai/docs/nodes/publish/webhook-output). המשתנה `SOCIAL_ENCRYPTION_KEY` הוא השם הישן, והוא עדיין עובד. |

**במערך השירותים המובנה של Compose, דלגו על השלב הזה.** הקונטיינר יוצר את שני הסודות באתחול. הוא שומר את מפתח ההצפנה ב-volume `app-data`, בנתיב `/data/nodaro/encryption-key`, ומשתמש בו שוב בכל אתחול שאחריו. גבו את ה-volume הזה יחד עם מסד הנתונים.

**באורקסטרציה משלכם**, כגון פלטפורמת אירוח או קונטיינרים נפרדים, הגדירו את שניהם בעצמכם:

```bash
echo "INTERNAL_ORCHESTRATOR_SECRET=$(openssl rand -hex 32)" >> .env
echo "NODARO_ENCRYPTION_KEY=$(openssl rand -hex 32)" >> .env
```

שמרו את `NODARO_ENCRYPTION_KEY` במקום בטוח ואל תשנו אותו לעולם: עם מפתח אחר, אי אפשר לקרוא שום דבר שהוא הצפין.

## 3. החלת המיגרציות של מסד הנתונים
**במערך המובנה זה קורה אוטומטית.** באתחול, האפליקציה מחילה את הקבצים ב-`supabase/migrations/` לפני שה-API עולה. היא זוכרת אילו קבצים החילה ומדלגת עליהם באתחול הבא. היא מסרבת לעלות מול מסד נתונים שהמיגרציות שלו הוחלו רק בחלקן, והיומן שלה מציין את הקובץ שנכשל.

**עם פרויקט Supabase מנוהל**, הגדירו `RUN_MIGRATIONS_ON_BOOT=false` והחילו את המיגרציות בעצמכם. ראו את הדף [מסד נתונים](https://nodaro.ai/docs/self-hosting/database#apply-the-migrations-to-a-managed-project).

## 4. הגדרת אחסון האובייקטים
### ה-MinIO המובנה
אין מה להגדיר. קובץ ה-Compose מגיע עם MinIO ועם ברירות המחדל האלה:

| משתנה | ברירת מחדל |
| --- | --- |
| `R2_ENDPOINT` | `http://minio:9000` |
| `R2_FORCE_PATH_STYLE` | `true` |
| `R2_BUCKET_NAME` | `nodaro-assets` |
| `R2_PUBLIC_URL` | `http://localhost:3000/storage/nodaro-assets` |

שרת הווב של האפליקציה מגיש את המדיה תחת `/storage/`, כך שהדפדפן וצד השרת ניגשים לאותה כתובת. ה-bucket נוצר באתחול הראשון, עם הרשאת קריאה ציבורית. המדיה נשמרת ב-volume `minio-data`.

כשמגישים את ההתקנה בדומיין אמיתי, הגדירו `R2_PUBLIC_URL=https://<your-domain>/storage/nodaro-assets`. שנו את פרטי הגישה של MinIO, `R2_ACCESS_KEY_ID` ו-`R2_SECRET_ACCESS_KEY`, לפני שחושפים את המערך.

### Cloudflare R2
מומלץ להשתמש ב-Cloudflare R2 בפריסות אמיתיות, כי אין בו עמלות על תעבורה יוצאת.

1. צרו bucket, למשל `nodaro-assets`, והגדירו את `R2_BUCKET_NAME` לשם שלו.
2. ב-**Settings** (הגדרות) של ה-bucket, הפעילו את הכתובת הציבורית `r2.dev` או חברו דומיין מותאם אישית. העתיקו את הכתובת הזו ל-`R2_PUBLIC_URL`.
3. תחת **Manage R2 API tokens** (ניהול אסימוני ה-API של R2), צרו אסימון עם ההרשאה **Object Read & Write** (קריאה וכתיבה של אובייקטים) על ה-bucket הזה. העתיקו את הערכים שלו ל-`R2_ACCESS_KEY_ID`, ל-`R2_SECRET_ACCESS_KEY` ול-`R2_ACCOUNT_ID`.
4. במערך השירותים של Compose, הגדירו גם את נקודת הקצה ואת סגנון הכתובות:

```bash
R2_ENDPOINT=https://<account-id>.r2.cloudflarestorage.com
R2_FORCE_PATH_STYLE=false
```

ערך ריק לא מנקה את שני המשתנים האלה: כשמשתנה ריק, קובץ ה-Compose חוזר לברירות המחדל של MinIO. מחוץ למערך השירותים של Compose, השאירו את שניהם לא מוגדרים, ונקודת הקצה נגזרת מ-`R2_ACCOUNT_ID`.

באתחול, היומן מציג שורה אחת לא מזיקה, `[storage] failed to create bucket` (יצירת ה-bucket נכשלה). אסימוני R2 לא יכולים ליצור buckets, וה-bucket שלכם כבר קיים.

### שירותי אחסון אחרים תואמי S3
ל-AWS S3, ל-Backblaze B2, ל-DigitalOcean Spaces, ל-Supabase Storage או ל-MinIO משלכם:

- הגדירו את `R2_ENDPOINT` לכתובת ה-S3 API של שירות האחסון.
- הגדירו `R2_FORCE_PATH_STYLE=true` ברוב השרתים באירוח עצמי.
- הגדירו את `R2_PUBLIC_URL` לכתובת הציבורית של ה-bucket.
- הגדירו את `R2_REGION` לאזור של שירות האחסון, אלא אם הוא Cloudflare R2 או MinIO.

ברירת המחדל של `R2_REGION` היא `auto`, הערך של Cloudflare R2 עצמו, ש-MinIO מתעלם ממנו. AWS, DigitalOcean Spaces (`nyc3`, `fra1` ועוד) ו-Supabase מקומי (`local`) דוחים את `auto`. במקרה כזה כל בקשה נכשלת עם שגיאת הרשאה או שגיאת נקודת קצה שלא מזכירה את האזור.

### הנגשת המדיה לקריאה ציבורית
יש שתי דרכים, ורוב ההתקנות צריכות רק את הראשונה:

1. **מדיניות bucket.** זו ברירת המחדל. עם `R2_ENDPOINT` מותאם אישית, האפליקציה יוצרת את ה-bucket באתחול ונותנת לו מדיניות של קריאה אנונימית. Cloudflare R2 לא צריך מדיניות כזו: הגדרת ה-bucket הציבורי שלו כבר דואגת לכך.
2. **ACL לכל אובייקט, עם `STORAGE_OBJECT_ACL`.** לשירותי אחסון שדוחים מדיניות bucket. DigitalOcean Spaces הוא המקרה הנפוץ: הוא דוחה מדיניות bucket ממפתח שמוגבל ל-bucket אחד. הגדירו `STORAGE_OBJECT_ACL=public-read`, וכל אובייקט שהאפליקציה כותבת מקבל את ה-ACL הזה.

השאירו את `STORAGE_OBJECT_ACL` ריק, אלא אם אתם צריכים את הדרך השנייה. כשהוא ריק, לא נשלחת כותרת ACL. כשהוא מוגדר בשירות אחסון שהמפתחות שלו לא מורשים להגדיר ACL, כל העלאה נכשלת. Nodaro מקבל את ערכי ה-ACL הסטנדרטיים המוכנים מראש — `private`, `public-read`, `public-read-write`, `authenticated-read`, `aws-exec-read`, `bucket-owner-read` ו-`bucket-owner-full-control` — ודוחה כל ערך אחר באתחול.

## 5. הפעלת המערך
```bash
docker compose -f docker-compose.community.yml up
```

אימג׳ האפליקציה, `ghcr.io/nodaroai/nodaro-community`, מורד כשהוא כבר בנוי. באתחול הראשון יורדים כ-2.4 GB במקום קומפילציה של 5–10 דקות, והאתחולים הבאים לוקחים שניות. היומנים של Redis ושל השירות `nodaro` מופיעים זה לצד זה. כשמופיעה השורה הזו, ה-API פעיל:

```text
nodaro-1  | server listening on http://0.0.0.0:9000
```

שרת הווב באותו קונטיינר מגיש את האפליקציה בפורט `3000`. פתחו את `http://localhost:3000`.

התג `latest` מתעדכן יחד עם הענף `main`. כדי לקבע גרסה ולקבל התקנה שאפשר לשחזר, הגדירו את `NODARO_IMAGE` ב-`.env`, למשל `NODARO_IMAGE=ghcr.io/nodaroai/nodaro-community:v1.23.0`. הדף [עדכון גרסה](https://nodaro.ai/docs/self-hosting/updating) מפרט את כל התגים.

כדי לבנות את האימג׳ מקוד המקור במקום זאת, הריצו `docker compose -f docker-compose.community.yml build`. צריך את זה רק כשמשנים את הקוד. הכתובת הציבורית, הפורט, הדומיין ומפתחות Supabase נקראים כשהקונטיינר עולה, כך שאחרי הפעלה מחדש האימג׳ שפורסם עובד עם הערכים החדשים.

## 6. התחברות ראשונה
הירשמו באפליקציה עם כתובת אימייל וסיסמה. שירות ההתחברות יוצר את המשתמש, ו-Nodaro יוצר את הפרופיל שלו אוטומטית. במערך המובנה לא נשלח אימייל אישור.

משתמשים במהדורת Community פועלים בלי הגבלות: אין ניהול קרדיטים ואין ממשק ניהול. במהדורת Business, השלב הבא הוא מינוי המנהל הראשון: ראו את הדף [המשתמש הראשון והמנהל](https://nodaro.ai/docs/self-hosting/first-admin).

## הקשחת ההתקנה לפני שחושפים אותה
ברירות המחדל של Compose מיועדות לשימוש מקומי, והן ציבוריות מעצם הגדרתן. לפני שאנשים אחרים יכולים להגיע להתקנה:

### יצירת מפתחות אימות חדשים
```bash
node tools/generate-selfhost-keys.mjs >> .env
```

הסקריפט מדפיס את `SUPABASE_JWT_SECRET`, `SUPABASE_ANON_KEY` ו-`SUPABASE_SERVICE_ROLE_KEY`. שני המפתחות חתומים עם הסוד, ולכן שלושתם חייבים להגיע מאותה הרצה. מפתח anon שהשתנה לא דורש בנייה מחדש: הקונטיינר מעביר אותו לדפדפן בזמן ריצה, ב-`/config.js`.

### הגדרת סיסמאות חדשות
הגדירו את `POSTGRES_PASSWORD` ו-`DATABASE_URL` תואם:

```bash
POSTGRES_PASSWORD=<new-password>
DATABASE_URL=postgres://postgres:<new-password>@db:5432/postgres
```

הגדירו גם פרטי גישה חדשים ל-MinIO ב-`R2_ACCESS_KEY_ID` וב-`R2_SECRET_ACCESS_KEY`.

מסד הנתונים מתאים את הסיסמאות של התפקידים הפנימיים שלו ל-`POSTGRES_PASSWORD` רק בהפעלה הראשונה שלו. אם ה-volume `db-data` כבר קיים, מחקו את ה-volume, מה שמוחק את הנתונים שלכם, או שנו ידנית את סיסמאות התפקידים בתור `supabase_admin`.

### הגשת ההתקנה ב-HTTPS
הגדירו את `PUBLIC_URL` לכתובת ה-`https://` האמיתית שלכם, והציבו פרוקסי הפוך לפני המערך. ראו את הדף [פרוקסי הפוך ו-HTTPS](https://nodaro.ai/docs/self-hosting/reverse-proxy).

### מי יכול להירשם
מהדורת Community מיועדת למנהל שרת יחיד. כל מי שמגיע לדף ההרשמה יכול ליצור חשבון, וכל משתמש מחובר יכול לשנות את מפתחות הספק. במהדורת Business, רק מנהלים יכולים לנהל את מפתחות הספק. ראו את הדף [מהדורות ופרופילי ממשק](https://nodaro.ai/docs/self-hosting/editions-and-profiles).

החילו כל שינוי עם `docker compose -f docker-compose.community.yml up -d`, ואז בדקו את הדף `/setup`.

## שאלות נפוצות

### מאיזה קובץ ‎.env כדאי להתחיל במערך השירותים של Compose?

במערך השירותים של Compose, העתיקו את ‎.env.community.example ל-‎.env. הקובץ הזה מפרט רק את מה שהמערך משתמש בו. הקובץ הגדול יותר, ‎.env.example, הוא קובץ עזר להתקנות מחוץ למערך, וערכי הדוגמה של Supabase שבו היו מחליפים את ברירות המחדל שעובדות.

### האם צריך ליצור את INTERNAL_ORCHESTRATOR_SECRET ואת NODARO_ENCRYPTION_KEY?

לא במערך השירותים המובנה של Compose, שיוצר את שני הסודות באתחול ושומר את מפתח ההצפנה ב-volume app-data. באורקסטרציה משלכם, הגדירו את שניהם ל-32 בתים אקראיים בייצוג הקסדצימלי, למשל עם openssl rand -hex 32.

### איך משתמשים ב-Cloudflare R2 במקום ב-MinIO המובנה?

כדי להשתמש ב-Cloudflare R2, הגדירו את R2_ACCOUNT_ID, R2_ACCESS_KEY_ID, R2_SECRET_ACCESS_KEY, R2_BUCKET_NAME ו-R2_PUBLIC_URL. במערך השירותים של Compose, הגדירו גם את R2_ENDPOINT לנקודת הקצה r2.cloudflarestorage.com של החשבון שלכם, וגם R2_FORCE_PATH_STYLE=false, כי ערכים ריקים חוזרים לברירות המחדל של MinIO.

### איך יודעים שההתקנה עלתה כמו שצריך?

ביומן של ההתקנה, חכו לשורה "server listening on http://0.0.0.0:9000" (השרת מאזין), ואז פתחו את http://localhost:3000/setup. כל הכרטיסים צריכים להיות ירוקים, חוץ מכרטיס מפתחות הספק עד שתוסיפו מפתח.

### מה צריך לשנות לפני שחושפים את ההתקנה לרשת?

לפני שחושפים את ההתקנה לרשת, צרו מפתחות אימות חדשים עם node tools/generate-selfhost-keys.mjs, הגדירו POSTGRES_PASSWORD חדש עם DATABASE_URL תואם ופרטי גישה חדשים ל-MinIO, הגדירו את PUBLIC_URL לכתובת ה-HTTPS שלכם, והציבו פרוקסי הפוך לפני ההתקנה.
