Linux servers
A Linux servers deployment runs your software on your customer's own Linux hosts: on-prem hardware, bare metal, or VMs in any provider, with no Kubernetes and no cloud account. Alien calls this platform Machines. The customer's admin runs one command on each host, and every release after that arrives without them.
Architecture diagram. Alien manages 3 remote environments: host-1 (customer-3 rack), https 443, outbound; host-2 (customer-3 rack), https 443, outbound; host-3 (customer-3 rack), https 443, outbound.
Each host runs a machine agent, a small service that connects out to Alien over HTTPS and runs the workloads Alien places on it. This is pull: the agent fetches each release, and nothing connects into the customer's network.
A deployment's life has two parts:
- Initial setup: the admin creates the deployment and runs a join command on each host, with root or
sudo. - Ongoing management: everything after. Alien places your workloads on the joined hosts and rolls out each release without the admin. Hosts keep running if the connection drops.
How the admin reaches initial setup is your Deployment UX choice: a link you send, a Deploy button in your product, or your own setup screen. What happens on the hosts is the same either way, and this guide follows it from requirements to removal.
Machines fit software that needs the host itself: sandboxes with nested virtualization, high-throughput processing on local disks, or anything next to existing on-prem systems.
For employee laptops and workstations, the local platform runs a Daemon, a long-running process, under supervision on the device.
What the customer needs
- Linux hosts with systemd, on
x86_64orarm64, with root orsudo. See Host requirements. - UDP
51820open between the hosts, and outbound HTTPS to Alien. - No Kubernetes and no cloud account.
Your stack
Declare a ComputeCluster pool with the hardware each host must have, and the workloads that run on it. Machines runs Daemon resources and stateless Container resources.
import * as alien from "@alienplatform/core"
const hosts = new alien.ComputeCluster("hosts")
.pool("general", {
requirements: {
cpu: 4,
memory: "16Gi",
ephemeralStorage: "100Gi",
dataDisk: { size: "200Gi" },
},
scale: { type: "fixed", machines: 3 },
})
.build()
const agent = new alien.Daemon("agent")
.code({ type: "image", image: "ghcr.io/acme/agent:2.1.0" })
.cluster("hosts")
.cpu(1)
.memory("1Gi")
.build()
export default new alien.Stack("acme-edge")
.platforms(["machines"])
.add(hosts, "frozen")
.add(agent, "live")
.build()On Machines, a pool is a label. Each host picks one when it joins, and Alien doesn't add or remove hosts.
dataDiskrequires an extra empty disk on every host.- The build rejects Worker, Build, ServiceAccount, and stateful Container resources for
machines, and public endpoints on Containers. - Only a Daemon with
runtime.networkMode: "host"can have a public endpoint. It serves HTTPS on port 443 of the host itself.
Create the deployment
For a customer, create a setup link that allows On-Prem. The admin opens it in the deployment portal, the branded setup page Alien hosts for them:
alien onboard customer-3 --platforms machinesIn the portal, the admin:
- Picks On-Prem, then Compute → Your machines.
- Clicks Set up machines.
- Copies the join command from the Connect machines panel. Generate new command issues a fresh one.
For your own hosts, in the dashboard, open Deployments → Deploy release → Deploy to your environment, then On-Prem → Your machines.
From the CLI:
alien deploy --name eu-edge --machinesThis creates the deployment and prints the join command. Until the first host joins, the deployment status is Waiting for machines.
Join a host
Run the same command on each Linux host:
curl -fsSL '<install-url>' | sudo bash -s -- join --token '<join-token>'The script installs your setup CLI, a setup package Alien builds under your command name (here acmectl), and runs join, which:
- Checks the host.
- Installs the machine agent as the
alien-machine.servicesystemd unit. - Waits up to 120 seconds for the host to register.
join flag | Description |
|---|---|
--token, --token-file | The join token (aj1_...) |
--capacity-group | The pool this host joins. Defaults to the only pool, or general. |
--zone | A physical or logical zone label for the host |
--network-interface | The interface to advertise to other hosts |
--public-ip | The IP that public endpoint DNS points to. A VPN-reachable private IP works. |
--wireguard-endpoint | The IPv4:port other hosts use to reach this one |
--dry-run | Print the join plan without installing anything |
Join tokens can carry an expiry and a join limit. Manage join tokens lists them, and Rotate all join tokens replaces them. From the CLI:
alien deployments join-tokens list <group>/eu-edge
alien deployments join-tokens create <group>/eu-edge
alien deployments join-tokens rotate <group>/eu-edge
alien deployments join-tokens revoke <group>/eu-edge <token-id>create and rotate print the join command with the new token. The token is shown only once.
Rotating stops new joins. Hosts that already joined stay connected.
Host requirements
Join checks these before it installs anything:
- Linux with systemd, on
x86_64orarm64, with root orsudo. containerd,wg(WireGuard tools), andnft(nftables). On apt-based systems join installs them; on dnf-based systems it prints the install commands.- Kernel WireGuard, with UDP
51820open between the hosts. - The pool's capacity: CPU at least the requirement, memory at least 90% of it, and
/var/lib/containerdat least 85% ofephemeralStorage. - An empty, unmounted disk of at least
dataDisk.size, when the pool declares one. - Outbound HTTPS to Alien.
Join enables IP forwarding. Hosts reach each other over a WireGuard mesh, and workloads find each other at <name>.svc.
How updates arrive
Ongoing management on Machines uses pull. The machine agent polls Alien over outbound HTTPS and applies each release on the deployment's release channel. Nothing connects into the customer's network.
The machine agent also updates itself:
- The agent checks each new version against its SHA-256 and starts it once before it replaces the old one.
- Hosts update one at a time. Each must stay healthy for 5 minutes before the next one starts.
- An agent that fails to start three times reverts to the previous version.
- Your workloads and public endpoints keep running during the agent update.
Offline behavior
The agent polls Alien every 5 seconds. If it can't reach Alien, the host keeps running the last plan it accepted:
- Running workloads continue.
- Crashed processes restart.
- Workloads come back after a reboot.
A plan is bound to the host that received it, so a cloned disk refuses to start it.
Machines in the dashboard
Open Manage machines on the deployment page. Each host appears under Connected machines with its replicas, CPU, memory, storage, network, and Machine agent version (marked outdated when behind).
A host is Ready, Unhealthy, Offline, Draining, or Drained.
To take a host out of service:
- Click Drain machine and set a deadline (default 6 hours). Alien moves work off the host. Force drain skips the wait.
- Click Remove machine. Force remove removes a host that is unreachable.
On the host itself, leave stops the agent and removes it from the host. --purge also removes its identity and state:
sudo acmectl leave --purgeFrom the CLI, alien deployments machines <group>/eu-edge --json lists the hosts and their state. The same steps take the machine ID it shows:
alien deployments drain-machine <group>/eu-edge <machine-id> --deadline 6h
alien deployments cancel-machine-drain <group>/eu-edge <machine-id>
alien deployments remove-machine <group>/eu-edge <machine-id>drain-machine --force skips the wait. --force and remove-machine ask for confirmation; pass --yes in scripts.
To run a command on a host for debugging:
alien debug exec eu-edge --machine <machine-id> -- df -hRemove it
Delete the deployment (Delete deployment, or alien deployments delete <group>/eu-edge), then remove the agent from each host with sudo acmectl leave --purge.
Limits
- Designed for clusters of up to about 10 hosts.
- No GPU workloads on Machines.
- Public endpoints use A records for the hosts' IPs, or a CNAME to the customer's own load balancer. They're served only by host-network Daemons (
MACHINES_CONTAINER_PUBLIC_ENDPOINT,MACHINES_DAEMON_PUBLIC_ENDPOINT).
Next
- Kubernetes: for customers with a cluster
- Push, pull, and air-gapped: how updates reach each kind of deployment
Kubernetes
A deployment in a customer's Kubernetes cluster: what the admin needs, Helm or a new EKS, GKE, or AKS cluster, the Operator that pulls releases, tunnels, and removal.
Single-tenant in your cloud
A deployment dedicated to one customer in your own cloud account: how to create it, infrastructure changes without rerunning initial setup, and a customer-managed key on AWS.