# Deployment auf gemietetem Ubuntu-VPS End-to-end Anleitung. Annahme: frischer Ubuntu 22.04/24.04 VPS, du hast root via SSH, Domain optional. Trading läuft gegen Kraken **Demo** (kein echtes Geld). ## 0. Was du brauchst - SSH-Zugriff zum VPS als `root` oder Sudo-User - Git-Remote (GitHub/GitLab/self-hosted) für lokal↔Server-Sync - API-Keys: Kraken Demo (https://demo-futures.kraken.com), Gemini, Anthropic, optional CryptoPanic - Discord-Webhook-URL - Tailscale-Account (kostenlos, https://tailscale.com) ## 1. Lokales Repo zu Git-Remote pushen Auf deinem Laptop: ```bash cd ~/code/aitrader git init git add . git commit -m "initial: aitrader bot + discord notifier" # auf GitHub: neues *privates* Repo "aitrader" anlegen, dann: git remote add origin git@github.com:DEIN_USER/aitrader.git git branch -M main git push -u origin main ``` > ⚠️ **Repo MUSS privat sein.** `.env` ist via `.gitignore` ausgeschlossen, aber Keys gehören niemals ins Repo. ## 2. VPS vorbereiten SSH zum VPS und als root: ```bash # UFW: nur SSH öffentlich ufw default deny incoming ufw default allow outgoing ufw allow 22/tcp ufw enable ufw status ``` ## 3. Tailscale installieren ```bash curl -fsSL https://tailscale.com/install.sh | sh tailscale up ``` `tailscale up` zeigt einen Login-Link → in Browser öffnen → mit Google/GitHub einloggen → Server taucht in deinem Tailnet auf. Schreib dir den **Tailscale-Hostnamen** auf (z.B. `aitrader-vps`), den nutzt du gleich fürs Dashboard. ```bash tailscale ip -4 # zeigt 100.x.y.z — die private Tailnet-IP tailscale status ``` Auch auf **deinem Laptop und Phone** Tailscale installieren und einloggen → alle drei Geräte sind im selben Mesh. **Test:** Vom Laptop aus `ping aitrader-vps` (Magic-DNS aktiviert in Tailscale-Admin) oder `ping 100.x.y.z`. ## 4. Repo auf den VPS clonen Als root oder Sudo-User auf dem VPS: ```bash sudo mkdir -p /opt cd /opt sudo git clone https://github.com/DEIN_USER/aitrader.git aitrader # oder mit SSH-Key: # sudo git clone git@github.com:DEIN_USER/aitrader.git aitrader sudo chown -R $USER:$USER /opt/aitrader cd /opt/aitrader ``` Wenn du **SSH-Keys** für GitHub nutzen willst (für `git pull` ohne Passwort): ```bash sudo -u aitrader bash -c 'ssh-keygen -t ed25519 -N "" -f ~/.ssh/id_ed25519' sudo cat /home/aitrader/.ssh/id_ed25519.pub # diesen Pub-Key in GitHub → Settings → Deploy Keys (read-only) fürs Repo eintragen ``` (Der `aitrader`-User wird im nächsten Schritt vom Install-Script erstellt — Reihenfolge: erst install.sh, dann SSH-Key generieren.) ## 5. Install-Script ausführen ```bash cd /opt/aitrader sudo bash deploy/install.sh ``` Das macht: - erstellt System-User `aitrader` - installiert Python 3.12, uv - legt venv unter `/opt/aitrader/.venv` an, installiert dependencies - kopiert systemd-Units nach `/etc/systemd/system/` ## 6. `.env` auf dem Server einrichten ```bash sudo cp /opt/aitrader/.env.example /opt/aitrader/.env sudo nano /opt/aitrader/.env # Trage ein: # KRAKEN_DEMO_KEY=... # KRAKEN_DEMO_SECRET=... # GEMINI_API_KEY=... # ANTHROPIC_API_KEY=... # DISCORD_WEBHOOK_URL=... # CRYPTOPANIC_API_KEY= (optional) sudo chown aitrader:aitrader /opt/aitrader/.env sudo chmod 600 /opt/aitrader/.env ``` ## 7. Smoke-Tests vor dem Start ```bash sudo -u aitrader /opt/aitrader/.venv/bin/python /opt/aitrader/scripts/smoke_kraken.py sudo -u aitrader /opt/aitrader/.venv/bin/python /opt/aitrader/scripts/smoke_ai.py sudo -u aitrader /opt/aitrader/.venv/bin/python /opt/aitrader/scripts/smoke_discord.py ``` Jeder Test sollte ohne Fehler laufen + der Discord-Webhook sollte 2 Embeds posten. ## 8. Bot + Dashboard als Services starten ```bash sudo systemctl enable --now aitrader.service sudo systemctl enable --now aitrader-dashboard.service sudo systemctl status aitrader aitrader-dashboard ``` Logs live anschauen: ```bash sudo journalctl -u aitrader -f sudo journalctl -u aitrader-dashboard -f ``` ## 9. Dashboard via Tailscale erreichen Auf deinem Laptop (Tailscale läuft): ``` http://aitrader-vps:8501 ``` oder ``` http://100.x.y.z:8501 ``` Port 8501 ist **nicht** öffentlich — UFW blockt ihn, Streamlit lauscht auf `0.0.0.0`, aber der Tailscale-Tunnel ist der einzige Weg rein. Wenn du noch paranoider sein willst, in `aitrader-dashboard.service` `--server.address` auf die Tailscale-IP setzen. ## 10. Updates deployen (Workflow) Lokal arbeiten, Änderung pushen, Server pullt + restartet: ```bash # auf dem Laptop cd ~/code/aitrader # … Änderungen mit Claude Code … git add . && git commit -m "fix: foo" && git push # auf dem VPS cd /opt/aitrader sudo -u aitrader git pull # bei Code-Änderungen reicht restart; bei neuen Dependencies erst: # sudo -u aitrader /home/aitrader/.local/bin/uv pip install -e . sudo systemctl restart aitrader aitrader-dashboard sudo journalctl -u aitrader -f ``` **Tipp:** Falls du häufig deployst, leg dir lokal eine Funktion an: ```bash # in ~/.bashrc deploy-aitrader() { ssh DEIN_VPS 'cd /opt/aitrader && sudo -u aitrader git pull && sudo systemctl restart aitrader aitrader-dashboard && sudo journalctl -u aitrader -n 30' } ``` ## 11. Backup Die SQLite-DB unter `/opt/aitrader/data/aitrader.db` enthält alle Trades + Decisions. Backup z.B. via cron: ```bash sudo crontab -e # Tägliches Backup nach /root/backups 0 3 * * * cp /opt/aitrader/data/aitrader.db /root/backups/aitrader-$(date +\%F).db ``` ## Troubleshooting | Problem | Check | |---|---| | `aitrader.service: status=1` | `journalctl -u aitrader -n 100` — meist fehlende ENV-Vars | | Kraken-Symbol nicht gefunden | Kraken Futures nutzt `PI_XBTUSD`-Symbole. `python -c "import ccxt; x=ccxt.krakenfutures(); x.set_sandbox_mode(True); x.load_markets(); print(list(x.symbols)[:30])"` und `pairs:` in `config.yaml` anpassen | | Dashboard nicht erreichbar | `sudo ss -tlnp \| grep 8501` (lauscht?), `tailscale ping aitrader-vps` (Mesh ok?) | | Webhook tot | Discord rate-limit (429)? `journalctl -u aitrader \| grep discord` | | Bot pausiert | `journalctl \| grep daily_loss_limit_hit` — Risk-Limit greift | ## Sicherheits-Checkliste - [ ] Repo ist **privat** auf GitHub - [ ] `.env` hat `chmod 600` und gehört `aitrader:aitrader` - [ ] UFW: nur Port 22 öffentlich offen - [ ] Tailscale `up`, Server im Tailnet - [ ] SSH: Password-Auth aus, nur Key-Auth (`PasswordAuthentication no` in `/etc/ssh/sshd_config`) - [ ] `exchange.sandbox: true` in `config.yaml` — **niemals** versehentlich auf `false` - [ ] Discord-Webhook regelmäßig rotieren falls geleakt