> ## Knowledge Base Index
> Fetch the complete knowledge base index at: https://documentation.celestory.io/sitemap.xml
> Use this file to discover available pages before exploring further.
> Pure-Markdown content can be obtained by appending a '.md' suffix to the content URLs listed in the sitemap (without the trailing slash).

# 🔒Celestory&Voltask self-host

# **Complete Guide — Self-hosting Celestory & Voltask on CasaOS**
> Installation and configuration guide for **Celestory & Voltask** on **CasaOS (the Celestory Kubb OS)**, designed for **non-developers**: every concept is explained, every setting is justified, and all common pitfalls are covered.
## **0. Who is this guide for?**
For anyone who wants to install Celestory & Voltask "at home" (on their own server) via **CasaOS**, **without being a developer**. We explain everything: what a container is, an environment variable, a port, etc. If you already know these concepts, jump straight to [section 4 (configuration)](#4-configuration--the-step-by-step-procedure).
## **1. The basic concepts (read once)**
Before touching anything, here are the 7 notions that come up all the time. Understanding them will save you 90% of the headaches.
### **🧱 A "container"**
Picture a **small sealed box** containing a program and everything it needs to run (its version of Node, its files, its settings). It's isolated from the rest of the machine. Celestory isn't **one** program: it's **11 containers** working together (the API, the database, authentication, etc.). This is what we call a **stack**.
### **🐳 Docker**
This is the engine that runs these boxes. CasaOS relies on it.
### **📋 The&#32;`docker-compose.yml`&#32;file**
This is the **recipe** for the stack: it lists the 11 containers, their settings, and how they talk to each other. On CasaOS, it's located here:
```
/var/lib/casaos/apps/big-bear-celestory-voltask/docker-compose.yml
```
👉 **Everything we're going to configure in this guide is this file** (either through the CasaOS interface or the command line).
### **🔧 An "environment variable"**
This is a **setting** passed to a container in the form `NAME = value`. For example `ADMIN_PASSWORD = password`. The program reads these variables at startup to know how to behave. This is the bulk of what we're going to modify.
### **🔌 A "port"**
A machine can run several services at the same time; the **port** is the "door number" that tells which service you want to talk to. Examples: a classic website = door **80** (http) or **443** (https). Celestory exposes its interface on door **1500**. Two types of ports not to confuse:
* **internal port**: used *inside* the box (between containers);
* **published port**: the door opened to the *outside*, the one you type into your browser.
### **🚪 The "gateway" (reverse proxy)**
One of the 11 containers is called `celestory-gateway`. It's the **doorman** of the stack: it's **the only entry point**. When you open the interface, you talk to the gateway, and **it** routes you to the right service based on the **path** of the URL:
* `…/celestory/api` → goes to the **API**
* `…/hub` → goes to the **Hub** (license management)
* `…/voltask` → goes to **Voltask** (the automation engine)
This is exactly why the **paths** in the URLs matter (see [section 4.2](#42-the-variables-to-set)).
### **🛡️&#32;`ORIGIN`&#32;and the "CSRF" protection — THE critical point**
The hub and auth of Celestory are built with a framework (SvelteKit) that has an **anti-hacking security** called *CSRF protection*. In short:
> The server **refuses** any sensitive action (like login) if the address it's sent from does **not exactly** match the address declared in the `ORIGIN` variable.
"Exactly" means: **same protocol** (`http` vs `https`), **same name** (`localhost` vs a domain), **same port** (`:1500`). The slightest difference = error:
```
{"message":"Cross-site POST form submissions are forbidden"}  ← error 403
```
👉 **The golden rule of this whole guide:** the `ORIGIN` variable (and its siblings) must be **identical, character for character, to the URL you type in your browser's address bar**. This is the #1 cause of login failures.
## **2. Overview: the 11 containers**
| **Container** | **Role (in plain terms)** |
| ---- |
| `celestory-gateway` | 🚪 The doorman — **sole entry point**, publishes the interface on port **1500** |
| `celestory-frontend` | 🖥️ The web interface you see |
| `celestory-api` | ⚙️ The application brain (cloud API) |
| `celestory-auth` | 🔑 Login / accounts (OAuth, tokens) |
| `celestory-hub` | 📜 **License** management (and admin) |
| `celestory-voltask` | 🤖 The Voltask **automation** engine |
| `celestory-orchestrator` | 🎬 Coordinates Voltask tasks |
| `celestory-generator` | 🏗️ Generates projects / files |
| `celestory-db` | 🗄️ The PostgreSQL database (all the data) |
| `celestory-plugins-bun` | 🔌 Plugins (Bun runtime) |
| `celestory-plugins-deno` | 🔌 Plugins (Deno runtime) |
They start **in order**: most wait for `celestory-hub` to be "healthy" before starting. **If the hub doesn't start, the whole stack stays blocked** (see [troubleshooting](#7-troubleshooting--common-pitfalls)).
## **3. Prerequisites**
* **CasaOS** installed and working (here: for the Celestory Kubb on WSL2 + native Docker, but it works the same on a real Linux server).
* The **"Celestory & Voltask"** application (`big-bear-celestory-voltask`) installed from the CasaOS store.
* Knowing how to open the CasaOS **terminal** (or connect via SSH).
* A **Celestory license** (the offering is paid, no free version — see [celestory.io/pricing](https://celestory.io/pricing)).
* A **fal.ai&#32;API key** if you want the AI generation features (see [`FAL_API_KEY`](#43--fal_api_key-variable-ai-generation)).
## **4. Configuration — the step-by-step procedure**
### **4.1 The principle: choose your "access address" once and for all**
Before filling in anything, decide **which URL you'll use to access Celestory**. This URL will be reused everywhere. Two typical cases:
| **Situation** | **Your access URL ("BASE")** |
| ---- |
| Local access, on the machine itself | `http://localhost:1500` |
| Access from the network, by IP | `http://192.168.x.x:1500` |
| Access by domain name behind a reverse proxy with HTTPS | `https://celestory.mydomain.com` (often **without** `:1500`, since the proxy handles the port) |
> 📌 **The port&#32;`:1500`&#32;is part of the address.** The interface is served on the published port **1500**. If you access it through this port, then the address goes **all the way to the port** — a concrete example of a real page: `http://localhost:1500/hub/licenses`. If your address bar shows `:1500`, then **all** your variables must contain `:1500`. (Remember the golden rule from [section 1](#%EF%B8%8F-origin-and-the-csrf-protection--the-critical-point).)
In what follows, we write **`BASE`** for your access URL. Example: `BASE =&#32;http://localhost:1500`.
### **4.2 The variables to set**
The gateway routes based on the **path** of the URL. So you must fill in the **full paths** in each variable:
| **Container** | **Variable** | **Value (replace&#32;`BASE`&#32;with your URL)** |
| ---- |
| `api` | `ORIGIN` | **`BASE/celestory/api`** |
| `auth` | `SELF_HOSTED_REDIRECT_URI` | **`BASE/celestory/callback`** |
| `hub` | `ORIGIN` | **`BASE/hub`** |
| `voltask` | `WEBHOOK_URL` | **`BASE/voltask`** |
**Concrete example with&#32;`BASE = http://localhost:1500`:**
| **Container** | **Variable** | **Value to enter** |
| ---- |
| `api` | `ORIGIN` | `http://localhost:1500/celestory/api` |
| `auth` | `SELF_HOSTED_REDIRECT_URI` | `http://localhost:1500/celestory/callback` |
| `hub` | `ORIGIN` | `http://localhost:1500/hub` |
| `voltask` | `WEBHOOK_URL` | `http://localhost:1500/voltask` |
> ⚠️ **Protocol consistency.** If you access via `http://`, **everything** must be `http://`. If you access via `https://`, **everything** must be `https://`. A mix = error 403 at login (the infamous CSRF protection).
### **4.3 🆕&#32;`FAL_API_KEY`&#32;variable (AI generation)**
**What is it?** [fal.ai](https://fal.ai/) is an online service that runs **AI models** (image generation, etc.). Celestory uses it for its AI generation features. Without this key, those features don't work.
**How to get it?** Create an account on fal.ai → *API Keys* section → generate a key (it looks like a long string of characters).
**Where to add it?** Add an environment variable:
```
FAL_API_KEY = your_fal_ai_key_here
```
on the service that does the generation (typically **`generator`**, and/or **`api`** depending on your version). When in doubt, add it to both — an extra variable is harmless.
### **4.4 🗑️ The&#32;`projectFiles`&#32;volumes: unnecessary**
**Reminder: what is a volume?** A container is "sealed": what it writes inside disappears if it's recreated. A **volume** is a **folder shared** between the inside of the container and the host machine's disk, to **keep** the files.
👉 In the current version, the `projectFiles` volumes (on the `api` and `generator` side) **are not needed**. If your install has them, you can **remove them** without breaking anything; and if you're starting from scratch, no need to add them.
### **4.5 ⚙️ Check the Hub's internal port (`PORT = 1402`)**
On some versions of the image, the hub ships with a **wrong internal port** that prevents the **whole** stack from starting (the hub stays "unhealthy", and all the other containers stay stuck in `Created`).
The hub **must** have:
```
PORT = 1402
```
(and **not** `1500` — `1500` is the port *published by the gateway*, not the hub's internal port). The gateway looks for the hub on `HUB_PORT = 1402`, and the health check also tests `1402`. If you see `PORT = 1500` in the `hub` block, **fix it to&#32;`1402`**. (Details and symptoms in [section 7](#7-troubleshooting--common-pitfalls).)
## **5. Where and how to change these settings?**
Two methods. **Pick one.**
### **Method A — via the CasaOS interface (recommended for non-devs)**
1. Open CasaOS → click on the **Celestory & Voltask** app → ⚙️ **Settings**.
2. At the top, tabs: `api`, `auth`, `db`, `frontend`, `gateway`, `generator`, `hub`, … Click on the service you want.
3. Scroll down to **"Environment variables"**. Change the **Value** next to the right **Key**, or click **+ Add** for `FAL_API_KEY`.
4. To remove a volume: **"Volumes"** section → click the ✕ on the row.
5. **Save** → CasaOS recreates the stack automatically.
> ⚠️ **Two pitfalls of the CasaOS interface:**After saving, check that the hub still has **`PORT = 1402`** (the UI may sometimes re-display it) — otherwise fix it **before** saving.An **"Installing NaN% / Error"** banner may appear: it's **purely cosmetic** when the stack has also been touched via the command line. Close it with the ✕, **do not click** "reinstall".
### **Method B — via the command line (faster, safer)**
Open the CasaOS terminal (or SSH). First define a shortcut to the file, **and make a backup**:
```
COMPOSE=/var/lib/casaos/apps/big-bear-celestory-voltask/docker-compose.yml
sudo cp $COMPOSE ${COMPOSE}.bak.$(date +%Y%m%d_%H%M%S)
```
> 🧠 **Two things you absolutely must know:**The `COMPOSE=…` variable **disappears if you close/reopen the terminal** (new session). If a `$COMPOSE` command returns a weird error (`unknown shorthand flag: 'd'`), it's empty → **retype the&#32;`COMPOSE=…`&#32;line**.Reading or editing this file requires **`sudo`** (otherwise: `Permission denied`).
Example: fix the hub's port and check the current settings:
```
# 1) Fix the hub's internal port (1500 → 1402) — risk-free, 1500 only exists here
sudo sed -i 's|PORT: "1500"|PORT: "1402"|' "$COMPOSE"
​
# 2) Check the origins / paths / key
sudo grep -nE 'ORIGIN|WEBHOOK|REDIRECT|FAL_API_KEY' "$COMPOSE"
```
For the origins/paths, the safest is to **edit the file** (with `sudo nano "$COMPOSE"`) and set the exact values from [table 4.2](#42-the-variables-to-set). Locate each service block (`api:`, `auth:`, `hub:`, `voltask:`) and fix the line under `environment:`.
Once the changes are made, **apply them** by recreating the stack:
```
sudo docker compose -f "$COMPOSE" up -d --force-recreate
```
Then watch the startup (Ctrl+C to exit the watch):
```
watch -n3 'sudo docker ps --filter "name=celestory" --format "table {{.Names}}\t{{.Status}}"'
```
🎯 **Goal: all 11 containers&#32;`healthy`.** The hub should turn healthy in 30–60 s, then the others start in cascade.
## **6. First login & license activation**
### **6.1 Logging into the Hub**
1. Open **exactly** your `BASE` URL in the browser (e.g. `http://localhost:1500`).
    * On `https` with a self-signed certificate: the browser shows a warning → **Advanced → Continue**, this is normal.
2. **CELESTORY HUB** login page. **Default** credentials (set in the `hub` block of the compose):
    * **Email**: `ADMIN_USERNAME` (default `demo@mail.com`)
    * **Password**: `ADMIN_PASSWORD` (default `password`)
> 🧠 **Important concept — the admin account is created ONLY ONCE.**
> The administrator account is written into the database **at the very first startup**, from the value `ADMIN_USERNAME` had **at that moment**. If you change `ADMIN_USERNAME` **afterwards**, it does **not** rename the existing account: log in with the **original email**. To really change the admin, you have to modify it in the database (or reset the database — destructive).
### **6.2 Activate the license**
1. Once logged in, go to the licenses page: `BASE/hub/licenses`
(e.g. `http://localhost:1500/hub/licenses`).
2. Enter your Celestory **license key** (purchased on [celestory.io/pricing](https://celestory.io/pricing)).
3. The hub validates the license → the Voltask/Celestory features unlock.
## **7. Troubleshooting — common pitfalls**
Table of real symptoms encountered during an actual install, with the solution.
| **Symptom** | **Cause** | **Solution** |
| ---- |
| **Login impossible**, error `{"message":"Cross-site POST form submissions are forbidden"}` **403** | The access URL ≠ the `ORIGIN` variable (different protocol, name **or port**) | Align `ORIGIN`/`REDIRECT`/`WEBHOOK` **exactly** with the address bar URL (cf. [4.1](#41-the-principle-choose-your-access-address-once-and-for-all)). `http`≠`https`, and `:1500` counts! |
| **The stack won't start**: `hub` `unhealthy`, and `api`/`frontend`/`generator`/`voltask`/`gateway` frozen in `Created` | The hub has `PORT = 1500` instead of `1402` → its health check fails in a loop → blocks all the services waiting on it | `sudo sed -i 's\ | PORT: "1500"\ | PORT: "1402"\ | ' "$COMPOSE"` then recreate (cf. [4.5](#45-%EF%B8%8F-check-the-hubs-internal-port-port--1402)) |
| `dependency failed to start: container celestory-hub is unhealthy` | Same cause as above | Same |
| `unknown shorthand flag: 'd' in -d` | The `$COMPOSE` variable is **empty** (new terminal session) | Retype the `COMPOSE=/var/lib/...` line then rerun |
| `Permission denied` when reading the compose | You need root rights | Prefix the command with `sudo` |
| CasaOS **"Installing NaN% / Error"** banner | CasaOS UI desync after a command-line recreation | **Cosmetic**: close with ✕. Do **not** reinstall (it would overwrite your fixes) |
| Login OK but an **AI generation** feature doesn't work | `FAL_API_KEY` missing or invalid | Add the fal.ai key (cf. [4.3](#43--fal_api_key-variable-ai-generation)) |
| Login with an admin email refused even though it works on another machine | The admin was *seeded* with a **different** email at first startup | Log in with **this** machine's original email |
### **Useful diagnostic commands**
```
# State of all containers
sudo docker ps -a --filter "name=celestory" --format "table {{.Names}}\t{{.Status}}"

# Which port the hub actually listens on (should show 1402)
sudo docker logs --tail 20 celestory-hub

# Check the configured origins/paths/key
sudo grep -nE 'ORIGIN|WEBHOOK|REDIRECT|FAL_API_KEY|PORT: "14' "$COMPOSE"

# Auth logs (useful if login fails on the server side)
sudo docker logs --tail 40 celestory-auth
```
## **8. Reference — example final values (`BASE = http://localhost:1500`)**
```
# --- api ---
ORIGIN = http://localhost:1500/celestory/api
SELF_HOSTED = true
FAL_API_KEY = <your_fal_ai_key>          # depending on version

# --- auth ---
SELF_HOSTED_REDIRECT_URI = http://localhost:1500/celestory/callback
USE_SELF_HOSTED_CLIENT = true

# --- hub ---
ORIGIN = http://localhost:1500/hub
PORT = 1402                               # ⚠️ definitely not 1500
ADMIN_USERNAME = demo@mail.com            # or your admin email
ADMIN_PASSWORD = password                 # change in production!

# --- voltask ---
WEBHOOK_URL = http://localhost:1500/voltask

# --- generator ---
FAL_API_KEY = <your_fal_ai_key>          # depending on version

# --- gateway ---
# publishes the interface on port 1500 (do not change HUB_PORT = 1402)
```
> 🔐 **In production**, you must change `ADMIN_PASSWORD`, the PostgreSQL password, and do not expose the interface over `http` on the Internet without a reverse proxy + HTTPS.
