Skip to content

Register and Connect a Server

Register a server, classify new workload placement, and complete the first connectivity test.

Updated View as Markdown

Goal

Register a Linux server you own as an Appaloft deployment target, and confirm Appaloft can reach it securely over SSH.

When to use this task

  • Onboarding a new server for the first time.
  • Migrating to a new machine, or temporarily troubleshooting a server’s connectivity.

Prerequisites

  • A Linux server reachable over SSH, that you have root or sudo access to.
  • An SSH key (a dedicated deploy key is recommended, rather than your personal login key).

Inputs and defaults

InputDescriptionDefault
hostAn explicit hostname, IPv4, or IPv6 addressNone, required; CIDR, URLs, and host:port forms are not accepted
portSSH port22
userThe system user used to connectNone, required
CredentialSSH key path / a saved credential / one-time inputNone, required
Display name / labelHelps you tell servers apart in the listOptional
Workload rolesPlacement intent for new workload categoriesEmpty: general purpose for all workload types

Server registration input should not include resource, environment, or domain-related fields — those are independent configuration layers.

Workload roles

Workload roles declare which categories of new workload a server is intended to accept. They are placement intent, not proof that the server is healthy, ready, or technically capable. Choose any combination of these canonical values:

  • deployment-runtime: may accept new application runtime placement.
  • artifact-builder: records intent to accept artifact build execution when a governed builder-placement path exists. It does not mean remote build execution is currently available or ready.
  • sandbox-worker: may accept new Sandbox placement, but isolation and provider capability checks still apply independently.

No roles means General purpose (all workload types). API and structured CLI output preserve this as workloadRoles: []; list and show output do not hide the empty array or interpret it as incapable.

Role changes affect new placement only. They do not drain, stop, move, cancel, or reinterpret existing workloads or historical placement records. Lifecycle, connectivity, readiness, capacity, tenant, and provider checks remain independent. Unknown or duplicate roles are rejected.

Register a classified server with repeatable --workload-role options:

appaloft server register \
  --name primary \
  --host 203.0.113.10 \
  --workload-role deployment-runtime \
  --workload-role artifact-builder

Replace the complete role set after registration:

appaloft server configure-workload-roles srv_primary \
  --workload-role deployment-runtime \
  --workload-role sandbox-worker

Restore general-purpose placement by passing no role options:

appaloft server configure-workload-roles srv_primary

Use appaloft server list or appaloft server show <serverId> to read the normalized role array. If a deployment is rejected because the selected server does not allow deployment-runtime, select an eligible server, configure that role, or restore the empty general-purpose set. Changing roles does not repair runtime readiness or add remote build or Sandbox capability.

Web steps

  1. Go to Servers, click Register server.
  2. Fill in the host, port, user, SSH credential, and optional workload roles.
  3. Submit the form, then inspect the normalized role set and connectivity result.

CLI steps

Prefer the single task command when onboarding the local machine or an SSH server:

# Local Mac/Linux direct target
appaloft server enroll --local --name "Local machine"

# Enroll a VPS through the local SSH agent
appaloft server enroll ssh://[email protected]:22 --name primary

# Or read a private key from a local file; key bytes never enter argv, output, or Server readback
appaloft server enroll ssh://[email protected] \
  --private-key-file ~/.ssh/appaloft_deploy

# A stored SSH credential can also be reused
appaloft server enroll ssh://[email protected] \
  --credential-id sshcred_primary

enroll reuses registration, credential attachment, connectivity diagnostics, runtime preparation, and Server show in order. After registration it first prints a server-enrollment-checkpoint/v1 value with the serverId. It prints server-enrollment/v1 only after runtime preparation reports ready and real readback completes. A later failure does not delete the Server; use that id with server credential, server doctor, server runtime prepare, or server show to repair and retry.

The SSH target accepts only ssh://user@host[:port]. Passwords, paths, queries, fragments, and other schemes are rejected before registration.

The granular commands below remain available for scripts and manual repair:

# Register an IPv4 server
appaloft server register \
  --name primary \
  --host 203.0.113.10 \
  --port 22 \
  --provider generic-ssh \
  --target-kind single-server

# Register an IPv6-only server
appaloft server register \
  --name ipv6-primary \
  --host 2001:db8::1 \
  --port 22 \
  --provider generic-ssh

# Manually rerun the connectivity test
appaloft server test srv_primary

# View server details (does not trigger a new connectivity test)
appaloft server show srv_primary

# Rename (only affects the display name)
appaloft server rename srv_primary --name "Primary SSH server"
# Replace the complete workload role set
appaloft server configure-workload-roles srv_primary \
  --workload-role deployment-runtime \
  --workload-role sandbox-worker

# Restore general-purpose placement
appaloft server configure-workload-roles srv_primary

Cluster targets like Docker Swarm need to explicitly declare their shape:

appaloft server register \
  --name swarm-cluster \
  --host 203.0.113.20 \
  --provider docker-swarm \
  --target-kind orchestrator-cluster

Existing Kubernetes clusters

A Kubernetes cluster is also an orchestrator-cluster, while its connection information is owned separately by a Runtime Target Profile. The profile persists URI-shaped opaque references only. It does not accept kubeconfig YAML, tokens, certificates, namespaces, or manifests as registration or deployment input.

Register the cluster target, then configure its connection reference:

appaloft server register \
  --name production-cluster \
  --host kubernetes.invalid \
  --port 6443 \
  --provider kubernetes \
  --target-kind orchestrator-cluster

appaloft server configure-runtime-target-profile srv_cluster \
  --connection-reference file:///absolute/path/to/kubeconfig \
  --routing-policy-reference builtin://kubernetes/ingress-controller/traefik-k3s

The public local composition resolves absolute file:// kubeconfig references by default and does not copy file contents into Server readback. To keep credentials separately, also configure a --credential-reference secret://... and inject a credential-aware adapter that can resolve it. Without that adapter, readiness and deployment fail closed instead of falling back to local Docker or another target.

Routed workloads also require an explicit routing policy reference. The public built-in reference above allows ingress only from Pods in kube-system whose exact selector is app.kubernetes.io/name=traefik; it does not allow a wildcard namespace, Pod selector, or CIDR. Clusters with another ingress topology must inject a resolver for their own opaque policy reference. An absent, unknown, or invalid policy remains blocked before apply.

Run the non-mutating readiness inspection after configuration:

appaloft server readiness srv_cluster

The response always normalizes API reachability, version, authorization, namespace isolation, routing, and storage checks without returning Kubernetes API DTOs or raw credentials. The Web Server detail page exposes the same profile dialog and readiness readback for cluster targets; HTTP/API, SDK, and MCP consume the same operation schemas.

When a Resource mounts a named StorageVolume, the Kubernetes backend creates a StatefulSet and PVC under a stable storage scope. A new Deployment receipt reuses the same workload and PVC, while cleanup of the old receipt leaves durable storage intact. Existing StorageVolume backup/restore operations can back up that PVC and restore it to a new independent PVC by default.

A helm-chart source enters a typed Helm lifecycle through the same deployment operation rather than accepting raw manifests. Chart reference, version, values secret references, hook policy, and timeout belong to the source binding. Execution renders a redacted review, performs an atomic upgrade/wait, and must prove the previous manifest after a failed upgrade. Cleanup uses the exact release identity and a foreground uninstall. For example:

appaloft deploy oci://registry.example.com/charts/storefront \
  --method helm \
  --helm-chart-version 1.7.3 \
  --helm-values-secret-ref secret://helm/storefront/production \
  --helm-hook-policy bounded \
  --helm-timeout-seconds 420

The same profile can be committed without raw values:

source:
  type: helm
  chart: oci://registry.example.com/charts/storefront
  version: 1.7.3
  valuesSecretReferences:
    - secret://helm/storefront/production
  hookPolicy: bounded
  timeoutSeconds: 420
runtime:
  strategy: helm

The public Helm lifecycle accepts absolute file://, OCI, or HTTPS chart references. Its default local values resolver accepts absolute file:// references; Cloud/Enterprise can inject a credential-aware values resolver for managed secret references.

Outbound Server Worker

When a Mac/VPS cannot or should not expose inbound SSH, the device can initiate one outbound mTLS Worker connection. It attaches to an existing public Server. Worker connection, generation, lease, and certificate state are separate readback; revoking a Worker never deletes or renames the Server.

With an authenticated Cloud/self-hosted profile from appaloft login:

appaloft server worker enroll --server srv_primary --name "My Mac"
appaloft server worker run

enroll uses the active authenticated profile to issue a short-lived one-time token, generates the private key/CSR on the device, and exchanges it for a short-lived mTLS certificate. The private key never leaves the device, and the token never enters argv, output, long-lived credentials, or Server readback. A self-hosted flow with an administrator-transferred token can still use stdin:

printf '%s' "$ONE_TIME_TOKEN" | appaloft server worker enroll \
  --server srv_primary --name "Build VPS" --token-stdin

server worker run keeps the outbound connection in the foreground so the device’s own service manager can supervise it. Docker/container execution is the default. If the device owner explicitly allows Appaloft to run Workspace/Dev host commands on that machine, set this only in the local Worker environment:

APPALOFT_SERVER_WORKER_ALLOW_HOST_SHELL=true appaloft server worker run

This opt-in is device-local and cannot be enabled remotely by Cloud. Use APPALOFT_SERVER_WORKER_ROOTS to further restrict accessible paths to owned roots separated by the platform path delimiter. Port forwarding also requires a short-lived single-target capability; the relay is not a general VPN.

appaloft server worker status --json
appaloft server worker revoke

revoke closes the current connection, fences stale generations, and removes the local Worker credential. The Server and persistent Workspace data keep their own lifecycle. Once connected, run appaloft dev . --server srv_primary; see Local Development Sessions.

Expected output and status

The connectivity test checks: whether DNS/IP and the port are reachable, whether SSH credentials work, whether the target user has the permissions needed to deploy, whether the base runtime environment meets requirements, and where necessary returns proxy- or Docker-related diagnostics. The result distinguishes hostname resolution failures, network/host unreachable, authentication failures, and host-key verification failures instead of a single generic error.

Verification

  • The command or Web UI shows the connectivity test passing.
  • Run appaloft server show srv_primary and confirm status, provider, and workloadRoles match what you expect.

Rollback / recovery

SymptomRecovery
Connection timeoutCheck host, port, firewall, and network path
Authentication failureCheck the SSH key, user, and authorized_keys on the server
Insufficient permissionsConfirm the target user can execute the commands deployment requires
Missing runtime environmentInstall or switch to a supported provider/runtime per the diagnostics

After the connectivity test passes, continue on to Managing SSH Credentials and Proxy Readiness And Terminal Sessions.

When you no longer need a server, deactivate it before deleting it:

appaloft server deactivate srv_primary
appaloft server delete-check srv_primary
appaloft server delete srv_primary --confirm srv_primary

The pre-delete safety check blocks deleting a server that’s still active, or still has deployment history, resources, domains, certificates, or retained audit records; deletion itself doesn’t automatically clean these up either.

Navigation

Type to search…

↑↓ navigate↵ selectEsc close