Deploying Conductor¶
How to build and deploy the docs site and MCP service to konstant-server.
What gets deployed¶
| Component | URL | Location on server |
|---|---|---|
| Docs site (MkDocs) | https://conductor-docs.hectorsanchez.eu |
/srv/apps/conductor-docs/current/ |
| MCP service (FastAPI) | https://conductor-konstant.hectorsanchez.eu |
/srv/apps/conductor/current/ |
The docs site is static HTML served by nginx. The MCP service is a socket-activated uvicorn process behind nginx.
Prerequisites¶
- SSH access to konstant-server as
sdhector(has passwordless sudo) - Repo cloned on the server at
/srv/apps/conductor/shared/repo - Python venv at
/srv/apps/conductor/shared/venv
Deploying the docs site¶
Build locally¶
bash
cd conductor/
pip install -r requirements-docs.txt
mkdocs build --strict
This produces site/ — static HTML. Verify locally:
bash
mkdocs serve # http://127.0.0.1:8000
Deploy to konstant¶
The site/ directory must be copied to the server. From Windows, build locally then upload:
```powershell
Build MkDocs locally first¶
mkdocs build --strict
Upload site/ to temporary location on server¶
scp -r site/* konstant:/tmp/docs-site/
Create a new release and activate it¶
ssh konstant "bash -c ' APP=/srv/apps/conductor-docs REL=\$(date -u +%Y%m%dT%H%M%SZ) mkdir -p \$APP/releases/\$REL rsync -a /tmp/docs-site/ \$APP/releases/\$REL/ ln -sfn \$APP/releases/\$REL \$APP/current echo \"Docs release: \$REL\" '" ```
The docs site is now live — nginx serves directly from the current symlink. No service restart needed.
Deploying the MCP service¶
Write a deploy script¶
Create a bash script with the deployment steps. Example pattern:
```bash
!/usr/bin/env bash¶
set -e REPO=/srv/apps/conductor/shared/repo APP=/srv/apps/conductor REL=$(date -u +%Y%m%dT%H%M%SZ)
Pull latest code¶
sudo -u deploy git -C $REPO pull origin main
Stage new release¶
sudo -u deploy mkdir -p $APP/releases/$REL sudo -u deploy rsync -a \ --exclude .git --exclude .venv --exclude venv --exclude shared \ --exclude pycache --exclude '*.pyc' --exclude .env \ --exclude archive \ $REPO/ $APP/releases/$REL/
Install dependencies¶
$APP/shared/venv/bin/pip install -q -r $APP/releases/$REL/requirements.txt
Activate release¶
sudo -u deploy ln -sfn $APP/releases/$REL $APP/current
Restart service¶
sudo systemctl stop conductor.socket conductor.service 2>/dev/null || true sudo pkill -f 'uvicorn conductor' 2>/dev/null || true sleep 1 sudo systemctl enable --now conductor.socket sudo nginx -t && sudo systemctl reload nginx
Verify¶
curl -fsS http://127.0.0.1:9093/health echo "Deployed: $REL" ```
Execute from Windows¶
```powershell
Upload and run the deploy script¶
scp deploy-script.sh konstant:/tmp/deploy-script.sh ssh konstant "bash /tmp/deploy-script.sh" ```
The pattern is always: write a bash script → scp it to the server → ssh and execute. This avoids PowerShell eating $() and -u flags in inline SSH commands.
Verify¶
```bash curl https://conductor-konstant.hectorsanchez.eu/health
{"status":"ok","service":"conductor","version":"0.2.0","connect":"/connect"}¶
curl -s -o /dev/null -w "%{http_code}" https://conductor-konstant.hectorsanchez.eu/
200¶
curl -s -o /dev/null -w "%{http_code}" https://conductor-docs.hectorsanchez.eu/
200¶
```
Release directory layout¶
``` /srv/apps/conductor/ ├── current → releases/20260727T192904Z # symlink to active release ├── releases/ │ ├── 20260727T185813Z/ │ └── 20260727T192904Z/ └── shared/ ├── venv/ # Python virtual environment ├── repo/ # Git clone of conductor ├── .env # Environment secrets └── conductor.sqlite # Runtime database
/srv/apps/conductor-docs/ ├── current → releases/20260727T184112Z └── releases/ └── 20260727T184112Z/ # Static site files ```
Endpoints¶
| Path | Auth | Purpose |
|---|---|---|
/ |
Open | Landing page with agent configs |
/health |
Open | Health check (JSON) |
/connect |
Open | Full connection guide (HTML) |
/connect.md |
Open | Connection guide (raw markdown) |
/mcp |
Bearer token or ?key= |
MCP endpoint |
Troubleshooting¶
| Problem | Check |
|---|---|
| Service down after deploy | ssh konstant "sudo systemctl status conductor.socket" |
| Socket won't start | ssh konstant "sudo journalctl -u conductor.socket -n 20" |
| 401 on landing page | Auth middleware may be blocking; check _OPEN_EXACT in auth.py includes "/" |
| Docs site stale | Rebuild MkDocs locally and redeploy site/ |
| pip install fails | The shared venv may need updating: ssh konstant "$APP/shared/venv/bin/pip install -r $APP/current/requirements.txt" |