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.
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.
| Type | Name / Host | Value | TTL |
|---|---|---|---|
| A | app | SERVER_IP | 300 (or Auto) |
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:
nslookup app.quorlasocial.com
3Prepare the server
Where: SSH into the server as root
3a. Updates, a working user, and the firewall
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
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
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:
ssh YOURNAME@SERVER_IP
4Get the code
Where: server, as 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:
cd /opt/quorla
chmod 600 .env
sed -i 's/\r$//' .env # removes Windows line endings, if any
nano .envCheck or add these lines. Leave everything else as it is.
| Setting | Value | Why |
|---|---|---|
APP_DOMAIN | app.quorlasocial.com | The address Caddy gets a certificate for. |
ACME_EMAIL | support@quorlasocial.com | Certificate expiry notices. |
DASHBOARD_SECRET | keep the existing value; if empty, run openssl rand -hex 32 and paste the result | Keeps people signed in across restarts. Changing it signs everyone out. |
ANTHROPIC_API_KEY | the key from step 1 | AI runs. Without it, audits and plans fail on the server. |
ALLOW_PUBLISH | false for now | You turn it on in step 9, after the PC is switched off. |
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:
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
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
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:
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:
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:
docker compose exec app node connector/scripts/test-meta.js
9Switch over
Who: Manesh on the PC, then you on the server
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, setALLOW_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:
schtasks /query /tn "SocialManagerScheduler"
# Only if it exists:
schtasks /delete /tn "SocialManagerScheduler" /f9b. On the server: turn publishing on
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:
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 -
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
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:
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 minuteTo 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 running | docker compose ps |
| Read recent app logs | docker compose logs --tail=100 app |
Restart after changing .env | docker compose up -d |
| Restart without changes | docker compose restart app |
| Stop everything | docker compose down |
| Check the Meta connection | docker compose exec app node connector/scripts/test-meta.js |
| Recover admin access if nobody can sign in | docker compose exec app node dashboard/server/scripts/add-user.js EMAIL "Name" admin (prints a new password once) |
| See disk space | df -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 see | Likely cause | Fix |
|---|---|---|
| Browser warns about the certificate, or the site doesn't load | DNS not pointing at the server yet, or ports 80/443 blocked | Check 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 up | docker compose logs --tail=100 app; usually a missing or mistyped line in .env. |
docker compose says Set APP_DOMAIN or Set ACME_EMAIL | Those lines are missing from .env | Add them (step 5). |
| Settings shows Meta "Invalid OAuth access token" | A space or tab after =, or the token was revoked | Fix 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 page | Not on HTTPS, or DASHBOARD_SECRET empty or changed | Always use https://; set DASHBOARD_SECRET once and don't change it. |
| Uploads or saving fail with "permission denied" in the log | Data folders not owned by user 1000 | sudo chown -R 1000:1000 data clients team reports branding |
| AI runs fail straight away | No API key, no credit, or a model name the key can't use | Check 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 move | Run the two relocate-paths.js commands from step 7. |
| The disk is filling up | Video uploads and backups | du -sh data/library backups; archive old library months elsewhere, or move to a bigger disk. |
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.