# Physical-host deployment Production services run directly on Debian 13 (Trixie) physical/virtual host processes managed by systemd. Docker is permitted only for disposable local or ECS smoke validation; it is not a production runtime dependency. The pinned baseline is [`versions.lock.json`](versions.lock.json): Go 1.27.1, `0.1.0-p1.20260919`, Debian 13 amd64 and Asterisk 22.10.1. The Go release package contains only our SIP Agent/Dispatcher business binaries and their systemd units. SaaS-provided MQ, OSS, AI and other infrastructure are endpoints, not packages deployed by this project; local chain validation may use isolated fixtures/mocks only. Secrets, certificates, SIP credentials, broker URLs and phone-log keys are injected separately. Before every real outbound attempt, obtain a fresh user confirmation in the current conversation and display the exact SIP channel, raw target number and packet-capture plan. Real SIP outbound calls are permitted only from 09:00 (inclusive) through 20:00 (exclusive), Asia/Shanghai time; outside that window the Agent/Dispatcher must fail closed rather than wait, retry, delay or switch trunks. A prior confirmation does not authorize retries or another target; stop after a failed attempt until a new confirmation is received. ## One deployment directory `deploys/` is the only deployment directory for local checks, physical-host packages, Asterisk installation, configuration examples and systemd services. There is no separate draft service set or compatibility deployment directory. ## Local and isolated checks From the project root: ```sh make check make release ./dist/sip-go-agent agent --help ./dist/sip-go-agent dispatcher --help ``` `make release` creates a local-development binary, module copies, SHA-256 checksums and a manifest. A dirty-source marker is preserved; a local build is not a signed production candidate or proof of external service acceptance. For an isolated Dispatcher-to-Agent startup check, prepare the strict Dispatcher JSON configuration from `config/dispatcher.json.example`, inject its referenced credentials outside the repository, and supply the deployment-owned endpoint inventory and mTLS files. The local acceptance script also requires a loopback RabbitMQ URL because `dispatcher --once` must prove it can publish through the configured broker; it fails closed when the URL is absent: ```sh GO_SIP_LOCAL_MQ_URL=amqp://guest:guest@127.0.0.1:33252/ \ ./scripts/acceptance-local.sh ``` The command below is the long-running endpoint check: ```sh SIP_GO_AGENT_MODE=mock \ DISPATCHER_DB=./dispatcher.db \ DISPATCHER_AGENT_ENDPOINTS_FILE=./deploys/config/agent-endpoints.example.json \ MTLS_CA_FILE=/path/to/ca.pem \ MTLS_CERT_FILE=/path/to/dispatcher.pem \ MTLS_KEY_FILE=/path/to/dispatcher.key \ ./dist/sip-go-agent dispatcher --config /path/to/dispatcher.json --once ``` The Dispatcher probes the configured Agent, verifies its boot identity and activates a session before use. Tenant commands cannot select an endpoint or certificate. Agent RPC listening uses `AGENT_GRPC_LISTEN` and deployment-provided mTLS files; an Agent-side peer allowlist can be supplied with `MTLS_PEER_CERT_FINGERPRINTS`. Never place credentials or private keys in this repository. Dispatcher owns its SQLite database; Agent owns a separate `AGENT_SPOOL` and has no business database. These are single-node, single-Agent/Cell/tenant checks, not multi-Cell or production acceptance. Local protocol tests do not replace the mandatory deployment/capture diagnostics below. Mock is not authorization for real calls or paid provider requests. ## Build an uploadable package From the project root: ```sh deploys/build-package.sh deploys/packages/sip-go-agent-0.1.0-p1.20260919-linux-amd64.tar.gz ``` The package includes its SHA-256 manifest, a non-root systemd deployment layout, and the fail-closed non-production capture-first entrypoint. The installer installs that entrypoint as `/usr/local/sbin/agent-call-nonprod-evidence` and adds a dedicated validated sudoers rule for `rogee`; it does not install `tcpdump` or silently weaken production gates. A dirty/unapproved source manifest is intentionally rejected by the installer unless `--allow-nonproduction` is supplied for smoke work. ## Install on Debian 13 Upload and extract the archive on the target host, then run as root: ```sh tar -xzf sip-go-agent-0.1.0-p1.20260919-linux-amd64.tar.gz ./install.sh ``` The installer verifies Debian 13 amd64, package checksums and the release manifest; creates `rogee`, `/opt/sip-go-agent`, `/etc/sip-go-agent` and `/var/lib/sip-go-agent`, installs both systemd units, and does not overwrite existing environment or PKI files. Configure the injected values and approved static Cell artifact, then start explicitly: ```sh systemctl enable sip-go-agent-agent.service sip-go-agent-dispatcher.service systemctl start sip-go-agent-dispatcher.service sip-go-agent-agent.service ``` Use `./install.sh --start` only after the environment, mTLS identity, broker ACL and static Cell artifact have been reviewed. Production mode never silently falls back to Mock. ## Non-production capture-first gate Development, `mock`, `mixed` and non-production `real` validation must use [`cell/nonprod-call-evidence.sh`](cell/nonprod-call-evidence.sh) as the single capture-first entrypoint. It refuses `production`, validates the approved trunk and whitelist target, verifies `tcpdump` raw-capture capability, records the pre-call Debian/systemd/ECS-facing facts plus Asterisk/PJSIP/channel/media state, enables the PJSIP logger, captures SIP UDP 5060 and RTP UDP 10000-10800 before the call command starts, and always stops capture/logger and writes redacted status plus SHA-256 facts on success or failure. Real calls reserve a daily attempt in `/var/lib/sip-go-agent/state/real-call-attempts.tsv` per `trunk + original target`; the fourth attempt is rejected fail-closed, while `--preflight-only` does not consume quota. Existing real evidence is counted when seeding the ledger. Run it only after a fresh current-conversation confirmation naming the exact trunk, raw target and capture plan; the command after `--` must execute as the non-root `rogee` user. Do not invoke the Agent directly for a non-production real/mixed call, do not retry inside the wrapper, and do not treat a missing PCAP or state snapshot as a pass. The private call output and raw capture stay under the mode-0700 evidence directory and must not be copied into repository long-term evidence without redaction. ## Cell boundary Asterisk remains the SIP owner and is installed as the separately approved physical Asterisk 22.10.1 Cell service. Asterisk and the SIP Agent are the only business-code services in this repository. The Go package does not rewrite `pjsip.conf`, embed SIP credentials, or run Asterisk in Docker. Management owns the immutable static Cell artifact and its systemd/maintenance release; the Go Agent consumes the approved artifact and reports the applied revision. RabbitMQ, OSS, AI providers and SaaS APIs are external infrastructure. They are not installed by `deploys/`; their production ACLs/endpoints are supplied by SaaS, while local validation uses explicitly isolated test infrastructure. For non-ECS/offline Alibaba OSS validation, use `deploys/env/dispatcher.offline-oss.env.example` (public `oss-cn-beijing.aliyuncs.com`); keep `dispatcher.env.example`'s internal endpoint for the separately managed production ECS profile.