{"id":1343,"date":"2026-02-15T20:14:32","date_gmt":"2026-02-15T20:14:32","guid":{"rendered":"https:\/\/docs.ai.drawconclusions.org\/?page_id=1343"},"modified":"2026-02-24T12:45:57","modified_gmt":"2026-02-24T12:45:57","slug":"server","status":"publish","type":"page","link":"https:\/\/docs.ai.drawconclusions.org\/?page_id=1343","title":{"rendered":"server"},"content":{"rendered":"<p>The app runs on a DigitalOcean droplet called dracox. Primary domain: ai.drawconclusions.org Docs domain: docs.ai.drawconclusions.org Domains are sourced from <code>server\/var_www\/config.xml<\/code> (source of truth). phpMyAdmin domain: pma.ai.drawconclusions.org SSH key: use <code>config.xml<\/code> value at <code>ssh\/local_key_name<\/code> (user: root) PHP (stable): 8.4.15 (latest release listed on php.net releases page; released 20 Nov 2025) Required software (server):<\/p>\n<h2>Software<\/h2>\n<ul>\n<li>Docker Engine<\/li>\n<li>Docker Compose<\/li>\n<li>Firewall: UFW<\/li>\n<li>Fail2ban<\/li>\n<li>Python 3<\/li>\n<li>Node.js 20+ (for frontend tooling, if needed)<\/li>\n<li>rsync (for deployments)<\/li>\n<\/ul>\n<p>Local tooling (Windows):<\/p>\n<h2>Rsync<\/h2>\n<ul>\n<li>rsync is installed locally via MSYS2.<\/li>\n<li>Path: <code>C:msys64usrbinrsync.exe<\/code><\/li>\n<\/ul>\n<p>Swap configuration:<\/p>\n<h2>Swap<\/h2>\n<ul>\n<li>Swap file enabled at <code>\/swapfile<\/code> (size: 2G).<\/li>\n<li><code>\/etc\/fstab<\/code> contains: <code>\/swapfile none swap sw 0 0<\/code>.<\/li>\n<\/ul>\n<p>UFW rules (recommended):<\/p>\n<h2>Rules<\/h2>\n<ul>\n<li>Default: deny incoming, allow outgoing.<\/li>\n<li>Allow SSH (22\/tcp) from any IP (key-based auth required).<\/li>\n<li>Allow HTTP (80) from anywhere.<\/li>\n<li>Allow HTTPS (443) from anywhere (Traefik terminates TLS).<\/li>\n<li>Internal Docker service URLs (e.g., <code>http:\/\/be-nginx<\/code>) remain HTTP-only and are not exposed publicly.<\/li>\n<\/ul>\n<p>Access policy:<\/p>\n<ul>\n<li>Only the admin IP is allowed to access the server (block all other IPs).<\/li>\n<li>Temporary during initial development.<\/li>\n<\/ul>\n<p>Access:<\/p>\n<h2>Access<\/h2>\n<ul>\n<li>Build host from config: <code>DROPLET_IP=&quot;$(python3 - &lt;&lt;&#039;PY&#039;nimport xml.etree.ElementTree as ETnprint((ET.parse(&#039;server\/var_www\/config.xml&#039;).getroot().findtext(&#039;domains\/droplet_ip&#039;) or &#039;&#039;).strip())nPYn)&quot;; SSH_KEY=&quot;$(python3 - &lt;&lt;&#039;PY&#039;nimport xml.etree.ElementTree as ETnfrom pathlib import Pathnkey=(ET.parse(&#039;server\/var_www\/config.xml&#039;).getroot().findtext(&#039;ssh\/local_key_name&#039;) or &#039;&#039;).strip()nprint(str(Path.home()\/&#039;.ssh&#039;\/key))nPYn)&quot;<\/code><\/li>\n<li>Test access: <code>ssh -i &quot;$SSH_KEY&quot; &quot;root@$DROPLET_IP&quot; &quot;echo ok&quot;<\/code><\/li>\n<\/ul>\n<p>Deployment access:<\/p>\n<h2>Access<\/h2>\n<ul>\n<li>Deployment uses rsync from the local machine (no git-based deploys).<\/li>\n<li>The server does not pull from git during deployment.<\/li>\n<\/ul>\n<p>phpMyAdmin access:<\/p>\n<ul>\n<li>Use the domain: https:\/\/pma.ai.drawconclusions.org\/<\/li>\n<li>Restrict access to the admin IP via Traefik (IP allowlist).<\/li>\n<li>Allowlist lives in <code>server\/var_www\/docker\/traefik\/dynamic.yml<\/code> under <code>pmd-allowlist<\/code>.<\/li>\n<\/ul>\n<p>Development workflow:<\/p>\n<ul>\n<li>Development happens locally, then changes are deployed to the server.<\/li>\n<\/ul>\n<p>Docs:<\/p>\n<ul>\n<li>DevDocs are WordPress pages at <code>https:\/\/docs.ai.drawconclusions.org<\/code> (publish via <code>python3 scripts_local\/publish_devdocs.py<\/code>).<\/li>\n<li>HTTP requests redirect to HTTPS for all domains.<\/li>\n<\/ul>\n<p class=\"developerdocs-id-search\" aria-hidden=\"true\">DeveloperDoc ID: dd_id_59ded457ab<\/p>\n","protected":false},"excerpt":{"rendered":"<p>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 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":1360,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"doc_category":[8],"doc_layer":[31],"class_list":["post-1343","page","type-page","status-publish","hentry","doc_category-server","layer-dd_id_cffc321500"],"_links":{"self":[{"href":"https:\/\/docs.ai.drawconclusions.org\/index.php?rest_route=\/wp\/v2\/pages\/1343","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/docs.ai.drawconclusions.org\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/docs.ai.drawconclusions.org\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/docs.ai.drawconclusions.org\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/docs.ai.drawconclusions.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1343"}],"version-history":[{"count":5,"href":"https:\/\/docs.ai.drawconclusions.org\/index.php?rest_route=\/wp\/v2\/pages\/1343\/revisions"}],"predecessor-version":[{"id":3894,"href":"https:\/\/docs.ai.drawconclusions.org\/index.php?rest_route=\/wp\/v2\/pages\/1343\/revisions\/3894"}],"up":[{"embeddable":true,"href":"https:\/\/docs.ai.drawconclusions.org\/index.php?rest_route=\/wp\/v2\/pages\/1360"}],"wp:attachment":[{"href":"https:\/\/docs.ai.drawconclusions.org\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1343"}],"wp:term":[{"taxonomy":"doc_category","embeddable":true,"href":"https:\/\/docs.ai.drawconclusions.org\/index.php?rest_route=%2Fwp%2Fv2%2Fdoc_category&post=1343"},{"taxonomy":"doc_layer","embeddable":true,"href":"https:\/\/docs.ai.drawconclusions.org\/index.php?rest_route=%2Fwp%2Fv2%2Fdoc_layer&post=1343"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}