Extra SSH/SFTP/FTPS accounts per client

By default an Octopus instance has one tenant account pair (oN / oN.ftp). BOA can provision one extra subaccount per Aegir Client — a separate SSH/SFTP/FTPS account scoped to only that client's sites. The Unix-account side is driven by manage_ltd_users.sh (its _manage_sec secondary-user pass, iterating the main tenant's clients/ directories); the Aegir-side request originates from a Client node's Users assignment.

The granularity is per Client, not per individual developer: each Aegir Client maps to exactly one shell subaccount, shared by everyone assigned to that Client. To give two people independent shell credentials, give each their own Aegir Client (see the accountability discussion below).

The Client + subaccount model

Octopus instance o1
   └── main account: o1 + o1.ftp           ← operator + primary tenant
   │
   └── Aegir Client "AcmeCorp"
   │      ├── subaccount: o1.acme            ← one shell account for this Client
   │      └── sites: acme-prod.example.com
   │                acme-staging.example.com
   │
   └── Aegir Client "WidgetCo"
          ├── subaccount: o1.widget
          └── sites: widget.example.com

Each subaccount has its own SSH key and password, its own lshell config, sees only sites belonging to its parent Client, and cannot touch other Clients' sites within the same Octopus.

Provisioning lifecycle

A subaccount is requested by assigning Drupal user(s) to a Client node in the Aegir UI (Client → Users). On submit, Aegir creates a Task to provision the account; within a few minutes the cron-driven manage_ltd_users.sh (the */3 root crontab entry) picks up the request and creates the Unix account.

The subaccount username format is <octopus>.<client> — e.g. o1.acme — where <client> is the Client's directory name reduced to lowercase alphanumerics. It carries no .ftp suffix (unlike the main oN.ftp tenant) and no per-developer segment.

What the subaccount can do

Same as the main oN.ftp account (lshell-restricted), but scoped to the sites of one Client:

  • cd into the Drupal codebase directories belonging to that Client's sites.
  • Run vdrush / composer against those sites only.
  • SSH key + SFTP file upload for those site directories.

It cannot see other Clients' sites, touch the host system, or bypass lshell.

Per-subaccount SSH keys

The subaccount's ~/.ssh/authorized_keys is at the standard path (home is /home/<oN>.<client>, mirroring the username):

/home/<oN>.<client>/.ssh/authorized_keys

The owner (or a manager with shell access) populates it via SFTP or by editing directly.

Password rotation

Subaccounts follow the same 90-day rotation policy as the main oN.ftp account. New passwords are emailed to the Aegir user's email address.

Removal lifecycle

Removing the user from the Client's Users list, or otherwise breaking the subaccount's state, is what triggers deletion — there is no dedicated removal Task. manage_ltd_users.sh's _kill_zombies pass (run from the */3 cron) detects a subaccount whose state has diverged and deletes it. State is considered diverged when any of these is true: the ~/sites symlink is missing, its target no longer exists, or the /home/<oN>.ftp/users/<oN>.<client> marker file is gone.

Deletion is immediate on that detection — there is no grace period and nothing configurable about the timing. The account is removed with deluser --remove-home, and the deleted home is written once as a backup tarball under /var/backups/zombie/deleted/<timestamp>/. That tarball is an archival copy for recovery, not a retained or reactivatable home — the live account and its home are gone at that point. A second sweep catches orphaned home directories with no matching passwd entry and moves them to the same backup location as .leftover-<name>.

Why per-Client subaccounts vs. a shared oN.ftp

Sharing the main oN.ftp account across customers carries operational risks that per-Client subaccounts remove:

  • Cross-Client snoopingoN.ftp can see every site on the instance, whereas a Client subaccount sees only its own Client's sites.
  • Blast radius on disable — rotating or disabling oN.ftp affects everyone; a Client subaccount can be retired independently.

This is BOA's preferred pattern for the agency model (one Octopus, one Aegir Client per customer, one shell subaccount per Client).

Because the shell account is per Client, not per person, individual-developer accountability is achieved by mapping one Aegir Client per individual — each person then gets their own oN.<client> account, key and log identity. Putting several developers under a single Client gives them a shared subaccount, so the log shows oN.<client> did X, not which person — the same accountability gap as sharing oN.ftp, just narrowed to one Client's sites.

Related