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:
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=truefor an HTTPS deployment;ASESTACK_SESSION_TTL=12hto limit session lifetime;ASESTACK_LOGIN_WINDOW=10mandASESTACK_LOGIN_MAX_FAILURES=8for login throttling; andASESTACK_TRUSTED_ORIGINSfor 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:
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:
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:
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:
- sign in on the final HTTPS hostname;
- enroll a clearly named test passkey;
- sign out and sign in with Use Passkey;
- confirm the dashboard loads and the login audit event exists;
- delete the test credential with current-password confirmation; and
- 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:
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/asestackand/var/lib/asestackoff-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.