- Refactored max_bot from nested packages to flat module structure - Q2: Extended BotUser model (patronymic, email, org, address, vcf_raw, contact_hash, phone_verified, email_verified, last_interaction, total_conversations, total_tickets) - Q2: VCF parser (FN, N, TEL, EMAIL, ORG, ADR), upsert on re-contact, NLP history context (_get_user_history_context -> YandexGPT) - Q1: Broadcast preview modal with 10s confirmation timer - Q3: CSS var(--white)->var(--bg-card), var(--text)->var(--text-primary) - Q4: bot_settings showNotification(), editable max_bot_id - Q5: Webhook secret passthrough via X-Max-Bot-Api-Secret - Masking sensitive keys, dialog_cleared handler, migrate via _add_column_if_not_exists() - Rate limit (asyncio.sleep 0.5 per 10), dead code removed, conv.intent context in contact.py - Portal pages: bot_consent, bot_kb (edit), bot_settings, bot_test, bot_tickets, portal_settings - Tests: 21/21 passing, added test_yandex_gpt.py, test_email_sender.py - Deploy: deploy_full.sh, schema.sql, seed_knowledge_base.sql
8.6 KiB
VPS Infrastructure Guide for AI Agents
Overview
This document describes the VPS infrastructure at 81.177.141.34 to help AI agents migrate or deploy new projects (e.g., voideaai.ru).
1. VPS Specifications
| Property | Value |
|---|---|
| IP | 81.177.141.34 |
| User | angel |
| Password | .-SHGWa_ |
| Sudo | passwordless via /etc/sudoers.d/angel |
| SSH key | added to ~/.ssh/authorized_keys |
| OS | Ubuntu 24.04 (Noble) |
| Kernel | OpenVZ/LXC container — limited kernel modules |
| Network interface | venet0 (no bridge NAT support) |
| Disk | 20GB total, ~13GB available |
| Docker | 29.5.0, iptables in nft mode (iptables-nft) |
2. Docker Constraints
Critical: network_mode: host only
Bridge networking (network_mode: bridge) does not work on this VPS. The OpenVZ/LXC kernel does not support masquerade for bridge interfaces through venet0. All containers must use:
network_mode: host
Docker daemon config (/etc/docker/daemon.json)
{"dns": ["8.8.8.8", "8.8.4.4"]}
Build constraint
All Docker builds require:
build:
network: host
Without this, apt-get and pip cannot download packages (no bridge NAT).
Docker Hub connectivity issues
Pulling large images (>100MB) from Docker Hub may time out (failed to copy: read tcp... connection timed out). Smaller images (nginx:alpine, postgres:16-alpine) work. Gitea and Portainer images cannot be pulled reliably.
Solutions attempted:
- Retry with
--platform linux/amd64 - Increase
max-download-attempts(not supported in Docker 29.5) - Clean build cache with
docker builder prune -af - All fail on large image layers
Workaround: Pull images locally and SCP (docker save → scp → docker load), or use a registry mirror.
3. Port Allocation (all on host)
| Port | Service | Container |
|---|---|---|
| 80 | nginx-proxy HTTP | nginx-proxy |
| 443 | nginx-proxy HTTPS | nginx-proxy |
| 8080 | PHP nginx (aegisone.ru) | aegisone-php-nginx |
| 9000 | PHP-FPM | aegisone-php-fpm |
| 8000 | FastAPI (service.aegisone.ru) | aegisone-app |
| 5432 | PostgreSQL (shared, aegisone) | aegisone-postgres |
| 5433 | PostgreSQL (Gitea) | gitea-db (planned) |
| 3000 | Gitea | gitea (planned) |
| 9001 | Portainer HTTP | portainer (planned) |
| 9443 | Portainer HTTPS | portainer (planned) |
Address resolution between containers
Since all containers use network_mode: host, they communicate via localhost:PORT. Docker DNS names do not resolve. In nginx.conf and app configs, use:
proxy_pass http://localhost:8080; # NOT container_name:port
4. Project Structure
/opt/projects/
nginx-proxy/ # Reverse proxy (nginx + certbot)
docker-compose.yml
nginx.conf
conf.d/ # Per-domain configs
certs/ # SSL certificates
html/ # Webroot for certbot
aegisone-php/ # PHP frontend (aegisone.ru)
docker-compose.yml
Dockerfile
nginx.conf # PHP nginx config (listen 8080)
src/ # PHP source files
aegisone-py/ # FastAPI backend (service.aegisone.ru)
docker-compose.yml
Dockerfile
app/ # Python source
sql/ # DB schema
gitea/ # Git hosting (planned)
docker-compose.yml
portainer/ # Docker UI (planned)
docker-compose.yml
5. nginx-proxy Configuration Pattern
Global config (nginx.conf)
resolver 127.0.0.11— not used in host mode, kept for compatibility- SSL termination handled by nginx-proxy
- Upstream protocols are HTTP (nginx-proxy terminates SSL and proxies via HTTP)
Conf.d file structure
Each domain has one .conf file with two server blocks:
# HTTP (no redirect — temporary, until LE certs)
server {
listen 80;
server_name example.ru;
location / {
proxy_pass http://localhost:PORT;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
# HTTPS (self-signed, for future LE)
server {
listen 443 ssl;
http2 on;
server_name example.ru;
ssl_certificate /etc/nginx/certs/live/aegisone.ru/fullchain.pem;
ssl_certificate_key /etc/nginx/certs/live/aegisone.ru/privkey.pem;
# ... same location block
}
Note: HTTP→HTTPS redirects (return 301 https://...) caused redirect loops externally due to provider/proxy intercepting port 443. If you add them, test thoroughly.
SSL certificates
Currently using self-signed certs generated via:
sudo openssl req -x509 -nodes -days 30 -newkey rsa:2048 \
-keyout /opt/projects/nginx-proxy/certs/live/aegisone.ru/privkey.pem \
-out /opt/projects/nginx-proxy/certs/live/aegisone.ru/fullchain.pem \
-subj '/CN=aegisone.ru'
For Let's Encrypt:
cd /opt/projects/nginx-proxy
docker compose run --rm certbot certonly --webroot \
--webroot-path=/var/www/certbot \
-d example.ru \
--email admin@example.ru \
--agree-tos --non-interactive
6. Deployment Workflow
Initial setup
- Prepare files locally (this repo)
- Pack into tarball:
tar czf project.tar.gz . - SCP to VPS:
scp project.tar.gz angel@81.177.141.34:/home/angel/ - SSH and extract:
ssh angel@81.177.141.34 "tar xzf project.tar.gz -C /opt/projects/project-name/" - Build and start:
ssh angel@81.177.141.34 "cd /opt/projects/project-name && docker compose up -d --build"
Updating a running project
- Edit files locally
- SCP changed files to
/home/angel/on VPS - SSH and copy to correct location:
sudo cp /home/angel/file /opt/projects/project-name/ - Restart container:
docker compose -p project-name restart service-name
Copying files into a running container (alternative to rebuild)
docker cp /home/angel/file.py container-name:/app/path/file.py
docker compose -p project-name restart app
7. Database
PostgreSQL (aegisone shared DB)
- Host:
localhost:5432 - User:
aegisone - Password:
aegisone_pass - Database:
aegisone - Container:
aegisone-postgres(postgres:16-alpine)
Schema initialization
SQL files in /opt/projects/aegisone-py/sql/:
schema_postgresql.sql— full schemaseed_data.sql— seed data
Init scripts run only on first volume creation. To add missing tables later:
docker exec -i aegisone-postgres psql -U aegisone -d aegisone < /opt/projects/aegisone-py/sql/schema_postgresql.sql
Key schema pattern
- All tables use
BOOLEANforis_active(not integer) - Timestamps use
TIMESTAMP NOT NULL DEFAULT NOW() updated_attriggers viaupdate_updated_at_column()function
8. Useful Commands
# Check running containers
docker ps -a
# Check compose projects
docker compose ls
# View logs
docker logs container-name --tail 50
# Restart service
docker compose -p project-name restart service-name
# Rebuild and restart
docker compose -p project-name up -d --build
# Clean build cache
docker builder prune -af
# Test nginx config
docker compose -p nginx-proxy exec nginx nginx -t
# Reload nginx
docker compose -p nginx-proxy exec nginx nginx -s reload
# Check listening ports
ss -tlnp | grep -E ':(80|443|8080|8000|9000|5432)'
# Check disk
df -h /
docker system df
9. Adding a New Project (e.g., voideaai.ru)
Steps:
- Create directory:
mkdir -p /opt/projects/voideaai - Create
docker-compose.ymlwithnetwork_mode: hostandbuild.network: host - Create
Dockerfile(use--only-binary :all:for pip if avoiding apt) - Create nginx-proxy config:
nginx/conf.d/voideaai.conf(listen 80, proxy_pass localhost:PORT) - Generate cert if needed
- Restart nginx-proxy:
docker compose -p nginx-proxy restart nginx - Start project:
cd /opt/projects/voideaai && docker compose up -d --build
Port allocation for new project
Check existing ports first (ss -tlnp). Choose an unused port for the app and add it to the nginx-proxy config.
10. Known Issues
- Docker Hub timeouts on large images — consider pulling on local machine and transferring with
docker save/docker load - HTTPS redirect loops externally — port 443 may be intercepted by provider/proxy; test HTTP first
- Bridge networking doesn't work — all containers must use
network_mode: host - Docker build needs
network: host— without it, apt-get/pip fail - Config files with
$in content — when editing via SSH from PowerShell,$variablesget expanded; use SCP (write locally, then copy)