Skip to content

Security

aseStack is a privileged control plane. It can inspect hosts and, when an operator deliberately enables the relevant guards, change containers, files, web-server configuration, certificates, firewall rules, databases, and backup state. Treat the controller, its backups, and every enrollment command as administrative credentials.

Start with the first-login hardening guide and publish the controller only through a correctly configured HTTPS reverse proxy.

Security model

The controller includes:

  • local users with role-based permissions;
  • hashed passwords, login rate limiting, secure session cookies, and CSRF protection for cookie-authenticated unsafe requests;
  • TOTP MFA, single-use recovery codes, passkeys, and optional Cloudflare Turnstile enforcement;
  • audit events for authentication, settings changes, and privileged actions;
  • encrypted backup-provider secrets with redacted API responses;
  • revocable, configurable-lifetime agent tokens plus mutual TLS;
  • path confinement for managed file operations and command allowlists for agent tasks; and
  • independent controller and managed-host guards for destructive actions.

These controls reduce risk; they do not make a publicly exposed controller safe without normal host hardening, backups, TLS, patching, and access review.

Users and roles

Use a named account for each person. Do not share the initial owner account.

Role Permissions
Owner Manage servers, sites, Docker, backups, files, databases, security, settings, and users; view audit history.
Operator Manage sites, Docker, backups, files, and databases; view audit history.
Viewer View audit history only.

The legacy admin role is treated as owner for compatibility, but new users must use owner, operator, or viewer.

Grant the least-privileged role that fits the person's work. Review the Users workspace and audit history after staff or responsibility changes.

Passwords and sessions

New and reset passwords must be at least 10 characters and contain English letters, numbers, and at least two special characters. The installer generates the initial password on a fresh installation. Change it at first login and do not leave the example password in the runtime environment.

The seed values ASESTACK_ADMIN_EMAIL and ASESTACK_ADMIN_PASSWORD create the initial owner. After /var/lib/asestack/users.json exists, changing the seed password does not overwrite an existing user's password.

If the owner password is lost, reset it on the controller:

sudo /opt/asestack/deploy/reset-admin-password.sh

The helper backs up the user store, resets the configured owner password, preserves the user-store permissions, and restarts the controller. It does not remove existing MFA fields. Protect the printed password and the backup copy.

Important session settings are:

  • ASESTACK_SECURE_COOKIES=true for an HTTPS deployment;
  • ASESTACK_SESSION_TTL=12h to limit session lifetime;
  • ASESTACK_LOGIN_WINDOW=10m and ASESTACK_LOGIN_MAX_FAILURES=8 for login throttling; and
  • ASESTACK_TRUSTED_ORIGINS for additional explicit browser origins.

Keep the direct local origin in ASESTACK_TRUSTED_ORIGINS when it is used for administration. Add only known origins. The reverse proxy must preserve the original Host header so same-host CSRF validation works as intended.

TOTP MFA and recovery codes

Each operator should enable TOTP MFA in Settings and save the generated recovery codes offline. Recovery codes are single-use; regenerate the set after using or exposing one.

Only enable the controller-wide policy after at least one owner has successfully enrolled MFA and stored recovery codes:

ASESTACK_REQUIRE_MFA=true

When enabled, the policy blocks password-only login and prevents an operator from disabling MFA. The Settings workspace refuses to enable the policy unless an owner already has MFA enabled.

Danger

Do not enable required MFA as a substitute for testing recovery. Verify a normal TOTP login and one recovery path first, and keep a current controller backup outside the host.

Turnstile

Turnstile is enabled when both keys are configured:

ASESTACK_TURNSTILE_SITE_KEY=<site-key>
ASESTACK_TURNSTILE_SECRET_KEY=<secret-key>

The site key is presented to the browser. The secret key must remain in the root-protected environment or the write-only Settings field. The controller also needs outbound DNS and HTTPS access to the configured verification endpoint.

If the widget renders but login reports turnstile verification failed, test outbound connectivity from the controller before rotating keys. Browser access to the challenge does not prove that the controller can reach the verification service.

Turnstile is optional at runtime, but ase passkey-check expects it by default. For an intentionally Turnstile-free deployment, run the preflight with ASESTACK_PASSKEY_CHECK_REQUIRE_TURNSTILE=false so the check matches the active policy.

Passkeys

Passkeys are WebAuthn credentials scoped to the controller's public hostname. A credential enrolled for one hostname cannot be used as proof for a different hostname.

Run the automated preflight on the controller:

sudo ase passkey-check https://control.example.com

The check verifies HTTPS, DNS, the health endpoint, login policy, WebAuthn relying-party ID, manual and conditional option endpoints, and the expected Turnstile enforcement. It does not exercise a real authenticator.

Complete the browser-device test as well:

  1. sign in on the final HTTPS hostname;
  2. enroll a clearly named test passkey;
  3. sign out and sign in with Use Passkey;
  4. confirm the dashboard loads and the login audit event exists;
  5. delete the test credential with current-password confirmation; and
  6. confirm the registration, login, and deletion events in Logs.

Conditional passkey prompts are controlled by the browser or password manager. A missing automatic prompt is not a failure if manual Use Passkey login succeeds.

When a security entrance is enabled, provide its full URL to the preflight only at execution time. Do not paste the path into documentation, issue trackers, or support bundles. The optional preflight summary records only that a path was configured, not the path itself.

Security entrance

The optional security entrance requires a secret URL path before the login form and authentication endpoints respond normally:

ASESTACK_SECURITY_ENTRANCE_MODE=required
ASESTACK_SECURITY_ENTRANCE_CODE=<long-random-path-component>
ASESTACK_SECURITY_ENTRANCE_RESPONSE_CODE=404

Allowed response codes are 200, 400, 401, 403, 404, 408, 416, and 444. An accepted entrance sets an HTTP-only cookie and redirects to the normal login form.

Warning

The security entrance conceals the shape of the control panel from casual scans. It is not authentication. Keep TLS, passwords, rate limiting, Turnstile where used, MFA, and passkeys in place.

Store the entrance code like a password. Do not include it in screenshots, monitoring URLs, browser-sync exports, shell transcripts, or public documentation. It must be 8–128 characters and contain only letters, numbers, hyphens, and underscores. Rotate it after accidental disclosure.

Agent identity and enrollment

Agent enrollment uses an API token and client mutual-TLS material. The controller's persistent CA is stored under:

/var/lib/asestack/agents/controller-ca.crt
/var/lib/asestack/agents/controller-ca.key

The private key is mode 0600. A backup of /var/lib/asestack therefore contains identity material capable of signing enrollment certificates and must be protected as a secret.

Generated enrollment commands contain the agent token and mTLS material. Run a command only on the intended host, do not save it in chat or tickets, and revoke the enrollment from Servers if it is exposed. Re-enrollment rotates the host's access. ASESTACK_AGENT_TOKEN_TTL controls the default authentication lifetime.

See Enroll a managed server for the normal workflow.

Provider credentials and backups

Secret backup-provider fields are encrypted with authenticated encryption using ASESTACK_BACKUP_CREDENTIAL_KEY. API responses redact those values. Back up the credential key with the controller configuration: losing it can make saved provider credentials unusable, while disclosure can expose them to anyone who also has the encrypted state.

Keep disposable deployment-validation credentials in a separate root-only file such as /etc/asestack/deployment-provider-check.env with mode 0600. Do not put them in source control or the normal runtime environment.

Protect control-plane backups because they may contain local users, enrollment identity, saved settings, audit history, and encrypted provider configuration. See Backups and restore for storage and restore guidance.

Guarded actions

Most host mutations are disabled by default. A controller flag authorizes a local action or permits a selected-server command to be queued. For managed servers, the corresponding agent-side flag must also be enabled before the host will execute it.

Controller-local guards

Action Controller setting Caveat
Docker start, stop, restart ASESTACK_DOCKER_ACTIONS=true Grants the controller access to live containers.
Docker system prune ASESTACK_DOCKER_PRUNE_ACTIONS=true Separate destructive guard; review reclaim scope first.
Docker exec ASESTACK_DOCKER_EXEC_ACTIONS=true Can run arbitrary allowed commands inside a container.
Native Nginx apply/disable/rollback ASESTACK_NGINX_ACTIONS=true Validate paths and commands; aseStack runs the configured Nginx test before reload.
UFW allow/deny ASESTACK_FIREWALL_ACTIONS=true Keep a second verified SSH session before changing firewall rules.
ClamAV scan ASESTACK_CLAMAV_SCAN_ACTIONS=true Limit ASESTACK_CLAMAV_SCAN_ROOT to the narrowest required readable path.
Read-only SQL console ASESTACK_SQL_CONSOLE=true Queries are limited to read-only statements and capped results.
Database import/export ASESTACK_DATABASE_TRANSFER_ACTIONS=true Transfers are plan-only while false and constrained to the transfer directory.
Backup-provider upload/download ASESTACK_BACKUP_PROVIDER_TRANSFER_ACTIONS=true Validate provider profiles and destination paths first.
Restore ASESTACK_RESTORE_ACTIONS=true Restores can replace controller state; verify the archive and maintenance window.
Automatic backup schedules ASESTACK_BACKUP_SCHEDULE_RUNNER=true Also requires provider transfer actions for live remote transfers.
Retention deletion ASESTACK_BACKUP_RETENTION_DELETE_ACTIONS=true Otherwise retention reports candidates as a dry run.

Managed-server paired guards

Action Controller queue guard Managed-host execution guard
Docker start, stop, restart ASESTACK_AGENT_DOCKER_ACTION_COMMANDS=true ASESTACK_AGENT_DOCKER_ACTIONS=true
Docker exec ASESTACK_AGENT_DOCKER_EXEC_COMMANDS=true ASESTACK_AGENT_DOCKER_EXEC_ACTIONS=true
Nginx apply, disable, rollback, cleanup ASESTACK_AGENT_NGINX_ACTION_COMMANDS=true ASESTACK_AGENT_NGINX_ACTIONS=true
Certificate issue or renew ASESTACK_AGENT_CERTIFICATE_ACTION_COMMANDS=true ASESTACK_AGENT_CERTIFICATE_ACTIONS=true
File writes ASESTACK_AGENT_WRITE_COMMANDS=true ASESTACK_AGENT_WRITE_ACTIONS=true
SQL queries ASESTACK_AGENT_SQL_COMMANDS=true ASESTACK_AGENT_SQL_ACTIONS=true
Database import/export ASESTACK_AGENT_DATABASE_TRANSFER_COMMANDS=true ASESTACK_AGENT_DATABASE_TRANSFER_ACTIONS=true
System snapshot create, transfer, staged restore, or rollback ASESTACK_AGENT_SYSTEM_SNAPSHOT_COMMANDS=true ASESTACK_AGENT_SYSTEM_SNAPSHOT_ACTIONS=true
System snapshot health probes ASESTACK_AGENT_SYSTEM_SNAPSHOT_HEALTH_CHECK_COMMANDS=true ASESTACK_AGENT_SYSTEM_SNAPSHOT_HEALTH_CHECKS=true

Enabling only the controller flag permits queueing; it does not override a disabled managed-host guard. Use the Servers workspace Preflight action and confirm the host's paths, binaries, permissions, backups, and recovery route before enabling either side.

Nginx cleanup can remove managed configuration and an explicitly confirmed document root or certificate lineage. It does not remove DNS records. Treat DNS cleanup as a separate provider operation. See Sites for the deployment lifecycle.

Audit and review

The Logs workspace records authentication and high-risk operator events, jobs, settings changes, deployment checks, backup and restore runs, and redacted agent command history. Review it after changing security policy or enabling an action guard.

For an offline handoff, export a signed operator-history archive and verify it with ase verify-operator-history. Keep the signing key separate from the archive. See Updates and the CLI.

Production checklist

  • Use the final HTTPS hostname before enrolling passkeys.
  • Change the initial password and create named accounts.
  • Enroll owner MFA and store recovery codes offline before requiring MFA.
  • Configure Turnstile policy intentionally and verify controller outbound access.
  • Keep the security entrance secret and treat it only as an additional layer.
  • Back up /etc/asestack and /var/lib/asestack off-host.
  • Run managed-host preflight before enabling paired action guards.
  • Keep firewall, restore, retention deletion, and Docker prune disabled until needed for a reviewed operation.
  • Review audit history and revoke stale enrollments regularly.
  • Apply controller and agent updates using the update guide.