dd_id_59ded457ab
4. System Technical
server
The app runs on a DigitalOcean droplet called dracox. Primary domain: ai.drawconclusions.org Docs domain: docs.ai.drawconclusions.org Domains are sourced from server/var_www/config.xml (source of truth). phpMyAdmin domain: pma.ai.drawconclusions.org SSH key: use config.xml value at ssh/local_key_name (user: root) PHP (stable): 8.4.15 (latest release listed on php.net releases page; released 20 Nov 2025) Required software (server):
Software
- Docker Engine
- Docker Compose
- Firewall: UFW
- Fail2ban
- Python 3
- Node.js 20+ (for frontend tooling, if needed)
- rsync (for deployments)
Local tooling (Windows):
Rsync
- rsync is installed locally via MSYS2.
- Path:
C:msys64usrbinrsync.exe
Swap configuration:
Swap
- Swap file enabled at
/swapfile(size: 2G). /etc/fstabcontains:/swapfile none swap sw 0 0.
UFW rules (recommended):
Rules
- Default: deny incoming, allow outgoing.
- Allow SSH (22/tcp) from any IP (key-based auth required).
- Allow HTTP (80) from anywhere.
- Allow HTTPS (443) from anywhere (Traefik terminates TLS).
- Internal Docker service URLs (e.g.,
http://be-nginx) remain HTTP-only and are not exposed publicly.
Access policy:
- Only the admin IP is allowed to access the server (block all other IPs).
- Temporary during initial development.
Access:
Access
- Build host from config:
DROPLET_IP="$(python3 - <<'PY'nimport xml.etree.ElementTree as ETnprint((ET.parse('server/var_www/config.xml').getroot().findtext('domains/droplet_ip') or '').strip())nPYn)"; SSH_KEY="$(python3 - <<'PY'nimport xml.etree.ElementTree as ETnfrom pathlib import Pathnkey=(ET.parse('server/var_www/config.xml').getroot().findtext('ssh/local_key_name') or '').strip()nprint(str(Path.home()/'.ssh'/key))nPYn)" - Test access:
ssh -i "$SSH_KEY" "root@$DROPLET_IP" "echo ok"
Deployment access:
Access
- Deployment uses rsync from the local machine (no git-based deploys).
- The server does not pull from git during deployment.
phpMyAdmin access:
- Use the domain: https://pma.ai.drawconclusions.org/
- Restrict access to the admin IP via Traefik (IP allowlist).
- Allowlist lives in
server/var_www/docker/traefik/dynamic.ymlunderpmd-allowlist.
Development workflow:
- Development happens locally, then changes are deployed to the server.
Docs:
- DevDocs are WordPress pages at
https://docs.ai.drawconclusions.org(publish viapython3 scripts_local/publish_devdocs.py). - HTTP requests redirect to HTTPS for all domains.