diff --git a/docs/hosting.html b/docs/hosting.html new file mode 100644 index 0000000..b6bb2d0 --- /dev/null +++ b/docs/hosting.html @@ -0,0 +1,411 @@ + + + + + +Quorla Server Setup + + + + + + + + +
+ + +
+
+
Hosting runbook
+

Set up Quorla on app.quorlasocial.com

+

This moves the social media dashboard from Manesh's Windows PC to a Linux server, so the whole team can use it from anywhere over HTTPS. Follow the steps in order. Commands are copy-and-paste; anything in CAPITALS is something you replace.

+
+ Time: about 1½–2 hours + Downtime: about 15 minutes (step 6 to step 9) + Skills: SSH and basic Linux commands +
+
+ + +

Caddy gets and renews the HTTPS certificate automatically. The app container also runs the publishing queue every 2 minutes, so nothing else needs scheduling.

+ +
+

1Before you start

+

Who: you, with Manesh for the items marked ★

+
    +
  • +
  • +
  • +
  • +
  • +
  • +
+
+ +
+

2Point the domain at the server

+

Where: the DNS settings for quorlasocial.com

+

Add one record. Do this first, because it can take a few minutes to an hour to spread.

+
+ + +
TypeName / HostValueTTL
AappSERVER_IP300 (or Auto)
+
If the DNS is on Cloudflare

Set the record to DNS only (grey cloud) for now. Caddy needs to reach the server directly to issue the certificate.

+

Check it from your own computer. It should print the server's IP:

+
Your computer
nslookup app.quorlasocial.com
+
+ +
+

3Prepare the server

+

Where: SSH into the server as root

+

3a. Updates, a working user, and the firewall

+
Server · root
ssh root@SERVER_IP
+
+apt update && apt -y upgrade
+apt -y install git ufw unattended-upgrades
+timedatectl set-timezone UTC
+
+# A normal user to run Quorla (replace YOURNAME)
+adduser YOURNAME
+usermod -aG sudo YOURNAME
+
+# Firewall: only SSH and web traffic
+ufw allow OpenSSH
+ufw allow 80/tcp
+ufw allow 443/tcp
+ufw allow 443/udp
+ufw --force enable
+
SSH keys

If you log in with a password, add your SSH key now (ssh-copy-id YOURNAME@SERVER_IP from your computer) and then turn off password logins in /etc/ssh/sshd_config (PasswordAuthentication no, then systemctl restart ssh).

+ +

3b. Install Docker

+
Server · root
curl -fsSL https://get.docker.com | sh
+usermod -aG docker YOURNAME
+docker --version
+docker compose version
+

Both version commands should print a version number. Log out, then log back in as your user for the rest of the guide:

+
Your computer
ssh YOURNAME@SERVER_IP
+
+ +
+

4Get the code

+

Where: server, as your user

+
Server · your user
sudo mkdir -p /opt/quorla
+sudo chown $USER:$USER /opt/quorla
+git clone https://git.metatroncube.in/MetatroncubeSoftwareSolutions/quorlasocial.git /opt/quorla
+cd /opt/quorla
+ls
+

You should see Dockerfile, docker-compose.yml, deploy/, dashboard/ and connector/. Git asks for your git.metatroncube.in username and password (or an access token) when cloning.

+

The repository contains only the program. Client files, logins, uploads and secrets are deliberately left out of Git; they come across in steps 5 and 6.

+
+ +
+

5Add the settings file

+

Where: server, in /opt/quorla

+

Put Manesh's .env file in /opt/quorla/.env (for example with scp .env YOURNAME@SERVER_IP:/opt/quorla/ from the computer where you received it). Then lock it down and open it:

+
Server · your user
cd /opt/quorla
+chmod 600 .env
+sed -i 's/\r$//' .env        # removes Windows line endings, if any
+nano .env
+

Check or add these lines. Leave everything else as it is.

+
+ + + + + + + + +
SettingValueWhy
APP_DOMAINapp.quorlasocial.comThe address Caddy gets a certificate for.
ACME_EMAILsupport@quorlasocial.comCertificate expiry notices.
DASHBOARD_SECRETkeep the existing value; if empty, run openssl rand -hex 32 and paste the resultKeeps people signed in across restarts. Changing it signs everyone out.
ANTHROPIC_API_KEYthe key from step 1AI runs. Without it, audits and plans fail on the server.
ALLOW_PUBLISHfalse for nowYou turn it on in step 9, after the PC is switched off.
+
No spaces after the = sign

Write KEY=value, never KEY= value. A stray space or tab becomes part of the value and breaks tokens. Save in nano with Ctrl+O, Enter, then Ctrl+X.

+

You don't need to change SCHEDULER_ENABLED, DASHBOARD_HOST or DASHBOARD_COOKIE_SECURE; Docker sets those for the server.

+
+ +
+

6Move the data from the PC

+

Who: Manesh on the PC, then you on the server. Downtime starts here.

+

6a. On Manesh's PC: stop the dashboard and pack the data

+

Stop the dashboard (close its terminal window, or press Ctrl+C in it), then in PowerShell:

+
Windows PC · PowerShell
cd D:\MCS_Repos\2026\claude_Metatron_Social_Media_Manager
+tar -czf quorla-data.tar.gz data clients team reports branding
+scp quorla-data.tar.gz YOURNAME@SERVER_IP:/opt/quorla/
+

This archive holds client files and everyone's (hashed) logins. Delete it from the PC once step 8 has passed.

+

6b. On the server: unpack it

+
Server · your user
cd /opt/quorla
+tar -xzf quorla-data.tar.gz
+sudo chown -R 1000:1000 data clients team reports branding
+rm quorla-data.tar.gz
+ls data   # should list: dashboard  library  schedule  publish-log.jsonl ...
+

The chown matters: the app inside Docker runs as user 1000 and must be able to write to these folders.

+
+ +
+

7Start Quorla

+

Where: server, in /opt/quorla

+
Server · your user
cd /opt/quorla
+docker compose up -d --build
+

The first build takes 3–6 minutes. Then fix the stored file locations (the PC used Windows paths like D:\…). Run it once to preview, then again with --write:

+
Server · your user
docker compose exec app node connector/scripts/relocate-paths.js
+docker compose exec app node connector/scripts/relocate-paths.js --write
+

The last line should say 0 file(s) not found. Then check both containers are running and watch the log for a moment:

+
Server · your user
docker compose ps
+docker compose logs -f --tail=50
+

app should show healthy after about 30 seconds, and the Caddy log should mention certificate obtained successfully. Press Ctrl+C to stop watching the log (Quorla keeps running).

+
+ +
+

8Check everything works

+

Where: your browser, signed in as an admin

+

Open https://app.quorlasocial.com. Everyone's existing logins came across with the data, so Manesh signs in with his usual email and password.

+
    +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
+

You can also check the Meta connection from the server:

+
Server · your user
docker compose exec app node connector/scripts/test-meta.js
+
+ +
+

9Switch over

+

Who: Manesh on the PC, then you on the server

+
Only one place may publish

If the PC and the server both run the queue, approved posts can go out twice. Finish 9a before 9b.

+

9a. On the PC: make sure nothing there can post

+
    +
  • In the PC's .env, set ALLOW_PUBLISH=false.
  • +
  • Don't start the dashboard on the PC again (no npm start).
  • +
  • Check that no Windows scheduled task exists for the queue; this should say the task cannot be found:
  • +
+
Windows PC · PowerShell
schtasks /query /tn "SocialManagerScheduler"
+# Only if it exists:
+schtasks /delete /tn "SocialManagerScheduler" /f
+

9b. On the server: turn publishing on

+
Server · your user
cd /opt/quorla
+sed -i 's/^ALLOW_PUBLISH=.*/ALLOW_PUBLISH=true/' .env
+docker compose up -d
+

In Settings → Connections, Publishing now says On. Every post still needs an admin's approval before it goes out. Downtime ends here.

+

9c. Tell the team

+

Send everyone the new address, https://app.quorlasocial.com. Their email and password are unchanged. The India team needs nothing extra: no VPN, just the browser.

+
+ +
+

10Set up daily backups

+

Where: server, as your user

+

deploy/backup.sh packs the settings, logins, uploads, queue, client files and reports into /opt/quorla/backups/ and keeps the newest 14. Run it once by hand, then schedule it for 02:30 UTC every night:

+
Server · your user
cd /opt/quorla
+sudo sh deploy/backup.sh
+( crontab -l 2>/dev/null; echo "30 2 * * * cd /opt/quorla && sh deploy/backup.sh >> backups/backup.log 2>&1" ) | sudo crontab -
+
Copy backups off the server

A backup on the same server doesn't survive the server being lost. Copy backups/ somewhere else weekly (another server, or encrypted cloud storage). The backups contain the .env with the Meta token and API keys, so keep them private and encrypted.

+

Restoring a backup

+
Server · your user
cd /opt/quorla
+docker compose down
+sudo tar -xzf backups/quorla-YYYY-MM-DD-HHMM.tar.gz
+sudo chown -R 1000:1000 data clients team reports branding
+docker compose up -d
+
+ +
+

Updating Quorla

+

When a new version is pushed to Git:

+
Server · your user
cd /opt/quorla
+sudo sh deploy/backup.sh
+git pull
+docker compose up -d --build
+docker compose ps        # app should be "healthy" again within a minute
+

To roll back, run git log --oneline, pick the previous version, then git checkout THAT_ID and docker compose up -d --build. Your data isn't touched by updates or rollbacks.

+

Avoid updating while a post is due in the next few minutes; the queue pauses for about a minute during the restart, and anything due in that time goes out right after.

+
+ +
+

Everyday commands

+

Run these from /opt/quorla.

+
+ + + + + + + + + + + +
To…Run
See if it's runningdocker compose ps
Read recent app logsdocker compose logs --tail=100 app
Restart after changing .envdocker compose up -d
Restart without changesdocker compose restart app
Stop everythingdocker compose down
Check the Meta connectiondocker compose exec app node connector/scripts/test-meta.js
Recover admin access if nobody can sign indocker compose exec app node dashboard/server/scripts/add-user.js EMAIL "Name" admin (prints a new password once)
See disk spacedf -h / and du -sh data clients backups
+

Adding teammates, resetting passwords and changing roles are done in the dashboard under Settings → Team members, not on the server.

+
+ +
+

Troubleshooting

+
+ + + + + + + + + + + + +
What you seeLikely causeFix
Browser warns about the certificate, or the site doesn't loadDNS not pointing at the server yet, or ports 80/443 blockedCheck step 2 with nslookup; check sudo ufw status and the hosting provider's own firewall panel; then docker compose restart caddy and read docker compose logs caddy.
"502 Bad Gateway"The app container isn't updocker compose logs --tail=100 app; usually a missing or mistyped line in .env.
docker compose says Set APP_DOMAIN or Set ACME_EMAILThose lines are missing from .envAdd them (step 5).
Settings shows Meta "Invalid OAuth access token"A space or tab after =, or the token was revokedFix the META_SYSTEM_USER_TOKEN line, then docker compose up -d. If it still fails, Manesh generates a new token in Meta Business Settings.
Signing in works but you're sent back to the sign-in pageNot on HTTPS, or DASHBOARD_SECRET empty or changedAlways use https://; set DASHBOARD_SECRET once and don't change it.
Uploads or saving fail with "permission denied" in the logData folders not owned by user 1000sudo chown -R 1000:1000 data clients team reports branding
AI runs fail straight awayNo API key, no credit, or a model name the key can't useCheck ANTHROPIC_API_KEY and the balance at console.anthropic.com; try DASHBOARD_AI_MODEL=claude-sonnet-5-5 in .env, then docker compose up -d.
Library thumbnails or scheduled posts say "file not found"Paths not relocated after the moveRun the two relocate-paths.js commands from step 7.
The disk is filling upVideo uploads and backupsdu -sh data/library backups; archive old library months elsewhere, or move to a bigger disk.
+
Keep port 4310 private

The app listens only inside Docker; the team always comes in through Caddy on HTTPS. Don't publish port 4310 in docker-compose.yml or open it in the firewall.

+
+ + +
+
+ + + +