> For the complete documentation index, see [llms.txt](https://docs.hivel.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.hivel.ai/archive/generic/hivel-on-premises-deployment-guide-generic/15.-security-and-secrets.md).

# 15. Security and Secrets

* **Where credentials come from:** the AWS Access Key ID/Secret Access Key used for ECR access are issued by Hivel directly (see AWS CLI Configuration) - they are not your own cloud account's credentials, and they're scoped to Hivel's ECR repository only. Database credentials are chosen by you when you provision the database (Database Setup); optionally, store them in a secrets manager (AWS Secrets Manager, Azure Key Vault, GCP Secret Manager, HashiCorp Vault) rather than only in config/.env.
* **Least privilege:** this guide already uses a two-phase credential pattern - root/master database credentials only for the one-time Flyway migration, then a scoped application user (\<user>) for all running services (see Environment Configuration and Database Migration). Don't duplicate root credentials into .env after migration completes.
* .**env is plaintext by design for this deployment model** - treat host filesystem access on VM1/VM2 as sensitive, and restrict who can read config/.env.
* **Rotating Hivel-issued ECR credentials:** Hivel has not published a fixed rotation cadence for the AWS ECR pull credentials it issues - contact your Hivel representative for the current process, including rotating on demand ahead of a security review. Never share these credentials outside your organization.
* **Rotating the application database password:** unlike ECR credentials, you can self-rotate this without re-running the Flyway migration:

1. Change the password at the database:

```
ALTER USER <user> WITH PASSWORD 'new_password_here';
```

2. Update config/.env to match (see the password-quoting rules in Environment Configuration):

```
# config/.env
DB_PASSWORD=new_password_here
```

3. Recreate the containers on each server so they pick up the new value - a restart alone is not enough, since environment variables are only re-read when containers are recreated, not when they're restarted:

```
./deploy.sh --vm1   # on VM1
./deploy.sh --vm2   # on VM2
```

* Two things to watch for:
* Existing pooled connections keep working on the old password until they reconnect - at which point they fail. Recreate the containers on both servers right away rather than waiting to find out which services are still holding a stale connection.
* Never use `./deploy.sh --all` for this - that flag deploys both servers' services onto a single instance and isn't used in this guide's two-server architecture.
* config/.env is interpolated by Docker Compose (${...} and $VAR are expanded), so a literal $ in the password must be escaped as $$. If the password contains # or spaces, wrap the whole value in single quotes.

<br>

{% columns %}
{% column %} <a href="/archive/generic/hivel-on-premises-deployment-guide-generic/14.-uninstall-and-cleanup.md" class="button primary" data-icon="backward">Uninstall and Cleanup</a>
{% endcolumn %}

{% column %}

{% endcolumn %}

{% column %} <a href="/archive/generic/hivel-on-premises-deployment-guide-generic/16.-quick-reference.md" class="button primary" data-icon="forward">Quick Reference</a>
{% endcolumn %}
{% endcolumns %}
