Install native Asterisk as a verified user systemd service
This commit is contained in:
+1
-1
@@ -7,7 +7,7 @@ by this project are:
|
||||
|
||||
- `sip-go-agent-dispatcher.service`
|
||||
- `sip-go-agent-agent.service`
|
||||
- the separately managed native `asterisk.service`
|
||||
- the separately managed native `go-sip-asterisk.service` under `rogee`'s `systemd --user` (production requires lingering)
|
||||
|
||||
RabbitMQ, OSS, AI providers and SaaS are external endpoints. They are not
|
||||
installed by the production package and are not started by systemd or Docker.
|
||||
|
||||
+15
-10
@@ -12,16 +12,21 @@ The pinned source input is:
|
||||
- Archive `../packages/asterisk-22.10.1-source.tar.gz`
|
||||
- SHA-256 `373c98f4d4a1b923b42def0aee03f4e36aca9d1c244a8eeda646da8a97f89663`
|
||||
|
||||
`build-asterisk-native.sh` can reproduce a native stage from the local pinned
|
||||
source/dependency archives using the Debian package list in
|
||||
`debian-build-packages.lock`; `install-asterisk-native.sh` installs that stage
|
||||
and the systemd unit without overwriting `/etc/asterisk`. Before production use,
|
||||
the Cell owner must verify its dependencies/licence/security review, install the
|
||||
management-approved static `pjsip.conf`/ARI/RTP configuration, and review/start
|
||||
the systemd unit explicitly. Do not silently substitute another Asterisk version or a
|
||||
container image. The Go Agent package only consumes the resulting approved static Cell artifact
|
||||
and reports its applied revision. Local validation may use isolated MQ/OSS/AI
|
||||
fixtures, but those are not production deployments.
|
||||
`build-asterisk-native.sh` reproduces the stage from the pinned source and
|
||||
local dependency cache; the build selects no downloaded core sounds/MOH.
|
||||
The native package includes its `build-platform` marker and
|
||||
`install-asterisk-user.sh`. Run that installer as `rogee`, never as root;
|
||||
it verifies the stage hash and required libraries, installs into `~/.local/opt/`,
|
||||
sets up `~/.config/go-sip-asterisk/` without overwriting existing files, and
|
||||
installs `go-sip-asterisk.service` under `systemd --user`. Production requires
|
||||
`loginctl enable-linger rogee` and a verified reboot-persistent `enabled+active`
|
||||
service; `--nonprod` allows a session-scoped Debian 12 native build but does
|
||||
not certify reboot persistence. The management-approved static `pjsip.conf`,
|
||||
ARI and RTP configuration must be supplied separately. The bundled stage has
|
||||
no live SIP trunk or dialing authorization; verify loaded endpoints and contacts
|
||||
before any call. Do not substitute another Asterisk version or a container image.
|
||||
The Go Agent package only consumes the resulting approved Cell artifact and
|
||||
reports its applied revision. Local Mock fixtures do not prove real services.
|
||||
|
||||
Before every real outbound attempt, the operator must obtain a fresh user
|
||||
confirmation in the current conversation that names the SIP channel, raw target
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
[Unit]
|
||||
Description=Asterisk SIP Cell 22.10.1 (physical host)
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=asterisk
|
||||
Group=asterisk
|
||||
WorkingDirectory=/var/lib/asterisk
|
||||
ExecStart=/usr/sbin/asterisk -f -U asterisk -G asterisk -vvvg
|
||||
ExecStop=/usr/sbin/asterisk -rx "core stop now"
|
||||
Restart=on-failure
|
||||
RestartSec=5s
|
||||
UMask=0077
|
||||
LimitNOFILE=65536
|
||||
PrivateTmp=yes
|
||||
ProtectHome=yes
|
||||
ReadWritePaths=/etc/asterisk /var/lib/asterisk /var/log/asterisk /var/spool/asterisk /var/run/asterisk
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -11,9 +11,10 @@ OUT=${OUT_DIR:-"$PKG/asterisk-$VERSION-native"}
|
||||
JOBS=${JOBS:-1}
|
||||
WORK=${WORK_DIR:-"$ROOT/.local/asterisk-build-$VERSION"}
|
||||
NONPROD=${NONPROD:-0}
|
||||
. /etc/os-release
|
||||
OS_ID=$(. /etc/os-release; printf '%s' "$ID")
|
||||
OS_VERSION=$(. /etc/os-release; printf '%s' "$VERSION_ID")
|
||||
source "$ROOT/deploys/cell/native-platform.sh"
|
||||
require_native_platform "$ID" "$VERSION_ID" "$(uname -m)" "debian:$VERSION_ID:x86_64" "$NONPROD"
|
||||
require_native_platform "$OS_ID" "$OS_VERSION" "$(uname -m)" "debian:$OS_VERSION:x86_64" "$NONPROD"
|
||||
|
||||
[[ -f "$SRC_ARCHIVE" && -f "$SRC_SHA" ]] || { echo 'Asterisk source archive/checksum missing' >&2; exit 1; }
|
||||
[[ -d "$DEPS" ]] || { echo 'Asterisk dependency cache missing' >&2; exit 1; }
|
||||
@@ -26,6 +27,10 @@ tar -xzf "$SRC_ARCHIVE" -C "$WORK"
|
||||
SRC="$WORK/asterisk-$VERSION"
|
||||
cd "$SRC"
|
||||
EXTERNALS_CACHE_DIR="$OUT/cache" ./configure --with-pjproject-bundled --with-jansson-bundled
|
||||
# Sound archives are not part of the pinned offline inputs; never fetch
|
||||
# unverified downloads during an otherwise reproducible native build.
|
||||
EXTERNALS_CACHE_DIR="$OUT/cache" make menuselect.makeopts
|
||||
./menuselect/menuselect --disable CORE-SOUNDS-EN-GSM --disable MOH-OPSOUND-WAV menuselect.makeopts
|
||||
EXTERNALS_CACHE_DIR="$OUT/cache" make -j"$JOBS"
|
||||
STAGE="$WORK/stage"
|
||||
rm -rf -- "$STAGE"
|
||||
@@ -35,11 +40,10 @@ EXTERNALS_CACHE_DIR="$OUT/cache" make install DESTDIR="$STAGE"
|
||||
# binary package.
|
||||
rm -rf -- "$STAGE/etc/asterisk"
|
||||
tar -C "$STAGE" -cpf "$OUT/asterisk-$VERSION-native-stage.tar" .
|
||||
cp "$ROOT/deploys/cell/asterisk.service" "$OUT/asterisk.service"
|
||||
cp "$ROOT/deploys/cell/install-asterisk-native.sh" "$OUT/install-asterisk-native.sh"
|
||||
cp "$ROOT/deploys/cell/install-asterisk-user.sh" "$OUT/install-asterisk-user.sh"
|
||||
cp "$ROOT/deploys/cell/native-platform.sh" "$OUT/native-platform.sh"
|
||||
printf 'debian:%s:x86_64\n' "$VERSION_ID" > "$OUT/build-platform"
|
||||
chmod 0755 "$OUT/install-asterisk-native.sh"
|
||||
printf 'debian:%s:x86_64\n' "$OS_VERSION" > "$OUT/build-platform"
|
||||
chmod 0755 "$OUT/install-asterisk-user.sh"
|
||||
(
|
||||
cd "$OUT"
|
||||
sha256sum "asterisk-$VERSION-native-stage.tar" > "asterisk-$VERSION-native-stage.tar.sha256"
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
[[ ${EUID} -eq 0 ]] || { echo 'install-asterisk-native.sh must run as root' >&2; exit 1; }
|
||||
START=false
|
||||
NONPROD=0
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
--start) START=true ;;
|
||||
--nonprod) NONPROD=1 ;;
|
||||
*) echo "unknown option: $arg" >&2; exit 2 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
PACKAGE_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)
|
||||
cd -- "$PACKAGE_DIR"
|
||||
. /etc/os-release
|
||||
[[ -f native-platform.sh && -f build-platform ]] || { echo 'native build platform metadata is missing' >&2; exit 1; }
|
||||
source ./native-platform.sh
|
||||
require_native_platform "$ID" "$VERSION_ID" "$(uname -m)" "$(<build-platform)" "$NONPROD"
|
||||
STAGE=asterisk-22.10.1-native-stage.tar
|
||||
sha256sum -c "$STAGE.sha256"
|
||||
[[ -f asterisk.service ]] || { echo 'asterisk.service is missing' >&2; exit 1; }
|
||||
getent group asterisk >/dev/null || groupadd --system asterisk
|
||||
id -u asterisk >/dev/null 2>&1 || useradd --system --home-dir /var/lib/asterisk --shell /usr/sbin/nologin --gid asterisk asterisk
|
||||
# Keep management-owned /etc/asterisk configuration intact.
|
||||
tar --exclude='etc/asterisk/*' -xpf "$STAGE" -C /
|
||||
ldconfig
|
||||
install -d -o asterisk -g asterisk -m 0750 /var/lib/asterisk /var/log/asterisk /var/spool/asterisk /var/run/asterisk
|
||||
install -o root -g root -m 0644 asterisk.service /etc/systemd/system/asterisk.service
|
||||
systemctl daemon-reload
|
||||
systemctl enable asterisk.service
|
||||
if [[ "$START" == true ]]; then
|
||||
systemctl restart asterisk.service
|
||||
fi
|
||||
/usr/sbin/asterisk -V
|
||||
printf 'installed asterisk=22.10.1 start=%s config_preserved=true\n' "$START"
|
||||
Executable
+85
@@ -0,0 +1,85 @@
|
||||
#!/usr/bin/env bash
|
||||
# Native, unprivileged Asterisk installation for the approved rogee user.
|
||||
set -euo pipefail
|
||||
nonprod=0
|
||||
if [[ ${1:-} == --nonprod ]]; then nonprod=1; shift; fi
|
||||
[[ $# == 1 ]] || { echo 'usage: install-asterisk-user.sh [--nonprod] <verified-native-package-dir>' >&2; exit 2; }
|
||||
[[ $(id -u) != 0 ]] || { echo 'do not run the user service installer as root' >&2; exit 1; }
|
||||
package=$(cd "$1" && pwd)
|
||||
. /etc/os-release
|
||||
source "$(dirname "$0")/native-platform.sh"
|
||||
[[ -f $package/build-platform ]] || { echo 'native build platform metadata is missing' >&2; exit 1; }
|
||||
require_native_platform "$ID" "$VERSION_ID" "$(uname -m)" "$(<"$package/build-platform")" "$nonprod"
|
||||
archive=asterisk-22.10.1-native-stage.tar
|
||||
(cd "$package" && sha256sum -c "$archive.sha256")
|
||||
if [[ $nonprod == 0 && $(loginctl show-user "$(id -un)" -p Linger --value) != yes ]]; then
|
||||
echo 'enable user lingering before a production user-service installation' >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
prefix="$HOME/.local/opt/go-sip-asterisk/22.10.1"
|
||||
config="$HOME/.config/go-sip-asterisk"
|
||||
state="$HOME/.local/state/go-sip-asterisk"
|
||||
data="$HOME/.local/share/go-sip-asterisk"
|
||||
cache="$HOME/.cache/go-sip-asterisk"
|
||||
unit="$HOME/.config/systemd/user/go-sip-asterisk.service"
|
||||
runtime="${XDG_RUNTIME_DIR:-/run/user/$(id -u)}/go-sip-asterisk"
|
||||
[[ ! -e $prefix && ! -e $unit && ! -e $config/asterisk.conf && ! -e $config/modules.conf ]] || { echo 'existing Asterisk installation or user configuration; refuse to overwrite' >&2; exit 1; }
|
||||
[[ $HOME != *[[:space:]]* ]] || { echo 'home path with whitespace is unsupported by the unit' >&2; exit 1; }
|
||||
|
||||
mkdir -p "$(dirname "$prefix")"
|
||||
staged=$(mktemp -d "$(dirname "$prefix")/.staged.XXXXXXXX")
|
||||
trap 'rm -rf "$staged"' EXIT
|
||||
tar -xpf "$package/$archive" -C "$staged"
|
||||
[[ -x $staged/usr/sbin/asterisk ]] || { echo 'native package has no Asterisk executable' >&2; exit 1; }
|
||||
if LD_LIBRARY_PATH="$staged/usr/lib" ldd "$staged/usr/sbin/asterisk" | grep -q 'not found'; then
|
||||
echo 'native Asterisk runtime libraries are missing' >&2; exit 1
|
||||
fi
|
||||
LD_LIBRARY_PATH="$staged/usr/lib" "$staged/usr/sbin/asterisk" -V
|
||||
mv "$staged" "$prefix"
|
||||
trap - EXIT
|
||||
|
||||
mkdir -p "$config" "$state/log" "$state/spool" "$data/db" "$data/keys" "$data/agi-bin" "$cache" "$(dirname "$unit")"
|
||||
cat > "$config/asterisk.conf" <<EOF
|
||||
[directories]
|
||||
astcachedir => $cache
|
||||
astetcdir => $config
|
||||
astmoddir => $prefix/usr/lib/asterisk/modules
|
||||
astvarlibdir => $data
|
||||
astdbdir => $data/db
|
||||
astkeydir => $data/keys
|
||||
astdatadir => $prefix/var/lib/asterisk
|
||||
astagidir => $data/agi-bin
|
||||
astspooldir => $state/spool
|
||||
astrundir => $runtime
|
||||
astlogdir => $state/log
|
||||
EOF
|
||||
printf '[modules]\nautoload=yes\n' > "$config/modules.conf"
|
||||
cat > "$unit" <<EOF
|
||||
[Unit]
|
||||
Description=Go SIP Cell native Asterisk (user service)
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=exec
|
||||
Environment=LD_LIBRARY_PATH=$prefix/usr/lib
|
||||
RuntimeDirectory=go-sip-asterisk
|
||||
WorkingDirectory=$data
|
||||
ExecStart=$prefix/usr/sbin/asterisk -f -C $config/asterisk.conf
|
||||
ExecReload=$prefix/usr/sbin/asterisk -C $config/asterisk.conf -rx "module reload res_pjsip.so"
|
||||
Restart=on-failure
|
||||
RestartSec=3
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
EOF
|
||||
systemctl --user daemon-reload
|
||||
systemctl --user enable --now go-sip-asterisk.service
|
||||
systemctl --user is-enabled go-sip-asterisk.service
|
||||
sleep 2
|
||||
systemctl --user is-active --quiet go-sip-asterisk.service || { echo 'Asterisk exited during startup' >&2; exit 1; }
|
||||
LD_LIBRARY_PATH="$prefix/usr/lib" "$prefix/usr/sbin/asterisk" -C "$config/asterisk.conf" -rx 'core show version' | grep -q 'Asterisk 22.10.1' || { echo 'Asterisk CLI did not report the expected live version' >&2; exit 1; }
|
||||
if [[ $(loginctl show-user "$(id -un)" -p Linger --value) != yes ]]; then
|
||||
echo 'nonproduction only: user lingering disabled; reboot persistence NOT verified' >&2
|
||||
fi
|
||||
@@ -0,0 +1 @@
|
||||
debian:13:x86_64
|
||||
@@ -10,8 +10,8 @@ to Debian 12. This exception does not approve production deployment or real call
|
||||
|
||||
Production remains a small systemd installation on Debian 13 amd64:
|
||||
|
||||
1. native Asterisk Cell (`asterisk.service`), owned by the approved SIP
|
||||
management release;
|
||||
1. native Asterisk Cell (`go-sip-asterisk.service`) under `rogee`'s `systemd --user`,
|
||||
with lingering enabled and reboot-persistent `enabled+active` verified;
|
||||
2. `sip-go-agent-agent.service`;
|
||||
3. `sip-go-agent-dispatcher.service`.
|
||||
|
||||
@@ -23,9 +23,12 @@ The pinned versions are in [`versions.lock.json`](versions.lock.json). Build
|
||||
a release candidate with `build-package.sh`; it writes the archive to
|
||||
`dist/packages/` and is intentionally not production-approved. Production
|
||||
installation requires a clean, externally approved manifest. Build/install
|
||||
Asterisk separately with the scripts in [`cell/`](cell/). The Asterisk
|
||||
installer preserves `/etc/asterisk`; the management-approved static Cell
|
||||
configuration is installed separately.
|
||||
Asterisk separately with the scripts in [`cell/`](cell/). The Asterisk user installer preserves existing files and places the Cell
|
||||
configuration under `~rogee/.config/go-sip-asterisk/`; management approves and
|
||||
updates `pjsip.conf` separately. Run `install-asterisk-user.sh --nonprod <native-package-dir>`
|
||||
for a Debian 12 test build; without `--nonprod`, user lingering is required
|
||||
before installation. Without lingering, non-production start is session-scoped
|
||||
and reboot persistence must be reported as unverified.
|
||||
|
||||
The Go installer creates `/opt/sip-go-agent`, `/etc/sip-go-agent` and
|
||||
`/var/lib/sip-go-agent`, installs the two Go units, and enables them. It does
|
||||
|
||||
Reference in New Issue
Block a user