Skip to content

Deploy on a VM with systemd

This guide stands up awcd and its dependencies as native systemd services on one Linux VM (spec §21.6). For a worked loopback pilot that runs PostgreSQL and MinIO in Docker, see Deploy on Proxmox VE.

Non-dev deploys need real TLS and signing keys

Development mode (AWC_DEV_MODE=1) is for loopback pilots only. For any host that is not loopback-only, provision mTLS identities and managed signing keys before you enable the services (spec §13.2). Agent processes SHOULD NOT receive object-store credentials or control-plane administrative tokens.

1. Provision a Linux VM that meets the host profile

The certified host profile requires (spec §15.1):

  • Linux kernel 6.1 or newer;
  • cgroup v2, FUSE, and OverlayFS enabled;
  • ext4 or XFS for the cache and workspace upper directories;
  • xattr support and /dev/fuse;
  • root or equivalent host capabilities for mount management;
  • a local SSD or NVMe for the cache volume;
  • outbound access to the control plane and the object store.

Use a full VM, not an unprivileged container. awcd needs the host mount namespace, /dev/fuse, and OverlayFS (spec §15.4). Put /var/lib/awc on a dedicated local volume. The cache and upper directories use that volume (spec §21.6).

2. Build and copy the package

On a Linux build host, build and sign the release tarball:

packaging/package.sh
# -> dist/awc-<version>-<target>.tar.gz

See Build and package for build options and signature verification. Copy the tarball to the VM.

3. Stand up PostgreSQL and an S3-compatible object store

Provision PostgreSQL and an S3-compatible object store. awc-control and awc-worker connect to PostgreSQL through a single DATABASE_URL. awcd and the worker read and write objects to the content-addressed store (CAS).

Keep the object-store credentials in /etc/awc/worker.env and /etc/awc/control.env. Do not pass them to agent processes (spec §13.2).

4. Install AWC, the awc user, and the unit files

On the VM, as root, unpack and install the package:

tar xzf awc-<version>-<target>.tar.gz
cd awc-<target>
./install.sh

install.sh creates the versioned layout under /opt/awc/, the unprivileged awc system user, the unit symlinks under /etc/systemd/system/, and default config under /etc/awc/. Default config is written only when absent. The script ends with systemctl daemon-reload. The install is idempotent and safe to re-run on upgrade.

The three unit files land at /etc/systemd/system/awcd.service, awc-worker.service, and awc-control.service. For the capability map, sandboxing, and the drain, restart, and rollback semantics, see systemd units. This guide does not repeat them.

5. Enroll the host and write the configuration

Enroll the host to write /etc/awc/awcd.toml and /etc/awc/awcd.env:

./enroll.sh --control-endpoint https://control.example.invalid

enroll.sh mints a host_id, writes the cache, workspace, and bind roots, and creates the state directories. Then fill in the deployment values:

  • /etc/awc/worker.env: DATABASE_URL, AWC_CAS_URL, and the S3 credentials.
  • /etc/awc/control.env: DATABASE_URL, the REST and gRPC listen addresses, the signing and service-token seeds, and the S3 credentials.

Install the PKI material that awcd.env and control.env reference:

/etc/awc/pki/ca.crt
/etc/awc/pki/awcd.crt        /etc/awc/pki/awcd.key
/etc/awc/pki/control.crt     /etc/awc/pki/control.key
/etc/awc/pki/mount-ticket.pub

awcd runs as the unprivileged awc user. It holds a bounded capability set, CAP_SYS_ADMIN included, so it can perform mount, FUSE, and cgroup operations without running as root (spec §15.3). The host identity uses an mTLS client certificate (spec §13.2). enroll.sh writes placeholder PKI paths only. It does not issue certificates.

6. Enable and start the units, then verify

Start the host daemon first, then the worker:

systemctl enable --now awcd
systemctl enable --now awc-worker

Enable awc-control only when your deployment has a control plane to serve. The ExecStartPost liveness gate marks awcd active only once /healthz answers (spec §19.6).

Verify the host:

awcctl status
curl -fsS http://127.0.0.1:9100/healthz
curl -fsS http://127.0.0.1:9100/readyz
journalctl -u awcd -f

awcd exposes liveness on /healthz and readiness for new mounts on /readyz (spec §19.6). Tail logs with journalctl -u <unit>. For drain, restart, and rollback, see Drain and restart a host and Upgrade a deployment.

Current scope

  • enroll.sh performs local enrollment: it mints a host_id and writes a placeholder control endpoint. For a real deployment, replace the placeholder with the control-plane endpoint and provision mTLS identity (spec §16.5). Host registration and the mTLS identity lifecycle are implemented.
  • awcd wires the control-plane client at startup: it attaches the lease lifecycle, the checkpoint publisher, and a background lease-renewal cache against the control endpoint. The endpoint is validated as a URL; a malformed endpoint disables the client but lets startup continue. Outside AWC_DEV_MODE=1, awcd and awc-control MUST present TLS credentials and fail to start without them (spec §13.2).
  • The awc-control, awcd, and awc-worker units are installed. Enable all three. See systemd units for the unit reference.
  • Quiesced checkpoints need a delegated execution cgroup. Cooperative checkpoints work without one.