Offline deployment
The product’s main form is enterprise intranet deployment, so “does it work offline” breaks down into two separate questions:
| Who | Needs internet? | Description |
|---|---|---|
| Employee machines | Not at all | Both client installers and update packages are delivered by the enterprise server (see Client delivery & updates) |
| Server | Only for “checking for updates + downloading images” | Reaching release.picoaide.com is enough; in a fully isolated environment, fetch packages via the bypass on this page |
Employee side: zero internet dependency
Section titled “Employee side: zero internet dependency”The server image already carries the client installers for all three platforms and serves them once deployment is complete. Employees only need to reach the enterprise domain — not the update server, GitHub or any public address.
Server side: how to fetch images in a fully isolated environment
Section titled “Server side: how to fetch images in a fully isolated environment”On any machine with internet access, download the image archive and the checksum file, then carry them into the intranet:
# 1) Read the version (authoritative fields: server.version / server.image_tag)curl -fsS https://release.picoaide.com/<channel>/latest.json
# 2) Download the image archive and the checksum fileVER=2.7.0curl -fL -o picoaide-server-${VER}-amd64.zip \ "https://release.picoaide.com/<channel>/releases/${VER}/picoaide-server-${VER}-amd64.zip"curl -fL -O "https://release.picoaide.com/<channel>/releases/${VER}/SHA256SUMS"
# 3) After copying into the intranet, verify and importsha256sum -c SHA256SUMSunzip -p picoaide-server-${VER}-amd64.zip image.tar | docker load- The update server keeps only the 3 most recent versions per channel; earlier versions come from the
GitHub Release (the complete historical archive for
public channels, with the same asset names
picoaide-server-<version>-amd64.zip+SHA256SUMS); - For slow cross-border downloads, use parallel chunking (measured: 75–260 KB/s single stream, about 2 MB/s with
8 parallel streams): for the method and pitfalls see
docs/planning/2026-09-10-r2-update-server-runbook.md§11 in the repository. Some Range requests are ignored by the CDN and return the whole file; the checksum is still the final arbiter; - Verify
SHA256SUMSbefore runningdocker load— there is no second acquisition channel inside the intranet, so a corrupt package means repeating the whole process.
After importing, the deployment steps are exactly the same as online; see Container deployment.
Disabling or reworking update checks
Section titled “Disabling or reworking update checks”By default the server checks for updates in this channel’s default directory (release.picoaide.com/<channel>/latest.json):
# Disable update checks (for a pure intranet where no outbound request is wanted)PICOAI_UPDATE_ENDPOINT=off- Leaving it empty does not turn it off: empty = use this channel’s default directory; to disable it you
must explicitly write
off/none/-/disabled; - If the intranet has its own static file service, you can also mirror the image archives and
latest.jsoninto the intranet and pointPICOAI_UPDATE_ENDPOINTat the intranet address (latest.json’schannel_idmust match this deployment’s channel, otherwise it is treated as “update check unavailable”); - Once disabled, the webadmin “Server info” page no longer shows new-version notifications, and upgrades are performed manually by operations following the upgrade procedure.
Offline upgrade cadence
Section titled “Offline upgrade cadence”A fully isolated deployment has no “new version notification”, so the version anchor relies on two manual checks:
cat /opt/picoaide/VERSION # currently deployed versiondocker exec picoaide-server /app/picoaide-server --version # running versionBoth should equal the target version written during the last upgrade. When upgrading, follow Upgrade, backup & rollback; the only difference is that the image source in step 4 becomes “the zip carried in from outside”.
Intranet certificates and client trust
Section titled “Intranet certificates and client trust”In internal mode, certificates are issued by Caddy’s local CA; the connection is encrypted, but the client has
to trust that CA on first connect:
- If the intranet has an enterprise CA, use
manualmode with a proper certificate and clients need no extra steps; - With
internalmode, distribute the Caddy root certificate to employee machines for import into their trust store; - In either mode, the client login page rejects non-HTTPS remote addresses (TOFU verification).
Post-deployment self-check (no DNS dependency; resolves directly to the local machine):
DOMAIN=$(grep '^DOMAIN=' .env | cut -d= -f2-)curl -sk --resolve "$DOMAIN:443:127.0.0.1" "https://$DOMAIN/healthz"curl -sk --resolve "$DOMAIN:443:127.0.0.1" "https://$DOMAIN/api/client/v2/updates/manifest"The second one must show client.assets with absolute https addresses — in intranet reverse-proxy/certificate
setups, PICOAI_PUBLIC_BASE_URL is the value most easily left unconfigured, and the symptom is that employee
clients “always say they are up to date”.