Core Panel

VPS Secrets Management: Secure .env Files and API Keys

CP
Written by Core Panel Team Product and documentation team · Published Oct 18, 2026 · 10 min read
VPS Secrets Management: Secure .env Files and API Keys
On this page · 10 sections

VPS secrets management covers the database passwords, API tokens, private keys, and application encryption keys that keep a hosted application working. Protecting them means controlling where they are stored, which processes can read them, and how they are replaced when access changes.

A .env file is a configuration format, not an encrypted vault. Keeping it out of Git is useful, but it can still leak through an incorrect web root, a debug page, a backup archive, or an overly permissive service account. This guide gives you a practical way to review those paths.

Inventory secrets without copying their values

Create an inventory that records the secret's purpose, owner, storage location, consumers, and replacement procedure. Record identifiers and access requirements rather than pasting credentials into a spreadsheet or ticket.

SecretTypical consumerQuestion to answer
Database credentialWeb app and background workersDoes it have only the required database privileges?
Email API tokenNotification workerCan it send mail without administering the provider account?
Storage credentialUpload and file-processing servicesWhich buckets and operations does it need?
Deployment credentialRelease pipelineCan it deploy only the intended application?
Encryption keyApplication encryption codeWhat existing data depends on keeping this key recoverable?

Separate production and staging credentials. Give unrelated applications different identities so that one leaked credential does not grant access to every site. The OWASP secrets management guidance explains least privilege and the lifecycle from creation through revocation.

Keep .env files outside the public web root

The web server should expose only the directory intended for public content. For Laravel, the official deployment guide directs requests through public/index.php and warns against serving the project root. It also requires production debug mode to be disabled because detailed error output can reveal configuration values.

Review every configured hostname and deployment path. A correct primary site does not prove that a temporary hostname or an older release is configured correctly. Keep configuration copies, editor backup files, and release archives out of publicly served directories.

Use a dotfile-deny rule as an additional layer where appropriate, following the framework's server example. Test that private configuration cannot be retrieved through your own site's intended request paths. A denied request checks one path; it does not establish that all copies are protected.

Choose permissions for the actual service account

Identify the operating-system identity that reads configuration. The PHP worker, a Node.js service, the deployment process, and a scheduled job may use different accounts.

For an owner-only regular file, mode 600 gives its owner read and write access while withholding ordinary group and other permissions. The GNU file-mode documentation explains this permission model. It only works operationally if the intended reader is the owner or receives access through another deliberately configured mechanism.

This read-only example displays metadata, not file contents. Replace the example path with your application's path:

stat -c '%a %U %G %n' /srv/example/.env

Check directory traversal permissions, group membership, and any access-control lists too. If several unrelated sites run as the same user, owner-only files do not isolate those sites from one another. Avoid making a configuration file readable by everyone to solve an ownership mistake.

Use a deliberate runtime delivery method

Choose the secret-delivery mechanism your application and service manager support. A restricted configuration file may be a starting point for a small deployment; a dedicated secret service can provide more centralized access control and auditing.

Environment variables are not automatically safer than files. They can be inherited by child processes and exposed by diagnostic tooling. systemd service credentials provide file-based delivery restricted to the service identity. Options such as LoadCredential= require compatible service code and a supported systemd version. Do not place a private key directly in a readable unit file using a literal SetCredential= value.

For a managed secret service, decide how the VPS authenticates before moving credentials into it. Google Secret Manager's best practices describe identity-based access and controlled secret versions. Avoid replacing several application secrets with one broadly privileged, permanently stored access key.

Test startup and recovery when the secret service is unavailable. A compromised application may still use secrets it is legitimately authorized to access, so secret storage complements application security and account isolation.

Keep credentials out of builds and troubleshooting output

Deployment pipelines can expose secrets before an application reaches the VPS. If you build container images, Docker recommends build secret or SSH mounts instead of embedding credentials through build arguments or Dockerfile environment settings. A secret mount does not protect a token that the build script subsequently prints or copies into an image layer.

Use placeholder values in example configuration. Review generated artifacts, release archives, and frontend bundles: anything shipped to a browser must be treated as visible to its users. Server-side API credentials belong on the server.

The OWASP logging guidance identifies access tokens, passwords, connection strings, and encryption keys as data that should not appear directly in logs. Prefer diagnostics such as whether a setting exists, a non-secret credential identifier, and the result of a connection check. Avoid sharing full environment dumps, verbose authenticated requests, or screenshots of credential pages.

Rotate credentials as a complete application change

Changing a stored value alone does not rotate the credential accepted by the destination service. AWS Secrets Manager's rotation documentation explicitly covers updating both the stored secret and the database or service.

For routine rotation where the provider supports two valid credentials during a short transition:

  1. Create a replacement with the required scope and record its non-secret identifier.
  2. Update the approved secret source and deploy the change to every consumer.
  3. Refresh configuration caches and reload long-running processes as required.
  4. Exercise the operations that use the credential, including background jobs.
  5. Revoke the previous credential at the provider and verify that it no longer authenticates.

If overlapping credentials are unsupported, plan a coordinated change and its expected interruption. For a suspected leak, use the incident-response process to contain access promptly; a routine overlap window is not a reason to leave a compromised key usable.

Laravel is a useful example of why editing one file is insufficient. Its configuration caching documentation explains that a cached application no longer loads .env during requests or Artisan commands. Update the cache through the deployment process and ensure workers adopt the intended configuration.

Handle application encryption keys separately

A database password authenticates a connection; an encryption key may be needed to recover existing data. Treating both as disposable strings can cause an outage or permanent loss of access to encrypted records.

Laravel documents encryption-key rotation, including a mechanism for retaining previous keys for decryption. Plan data migration and session behavior before changing APP_KEY. Follow the documentation for the installed framework version.

If a key has been exposed, retaining it as an accepted previous key is not complete remediation. Determine which data and sessions it protects, how to replace or re-encrypt affected material, and when the old key can stop being accepted. Keep required historical decryption material in controlled recovery storage rather than deleting it blindly.

Respond to an exposed secret before cleaning up history

If a real credential appears in a repository, public response, or shared log, identify its issuer and revoke or replace it promptly. GitHub's sensitive-data removal guidance puts revocation or rotation first. Removing a file in a later commit does not invalidate a copied credential.

Determine the permissions it granted, when it was exposed, and whether provider activity shows unexpected use. Preserve useful incident evidence without creating more plaintext copies. Then coordinate cleanup of repository history, build artifacts, caches, or logs as applicable.

Adding an ignore rule prevents some future mistakes; it does not erase earlier commits or copies held elsewhere. Document how the secret escaped and add a targeted preventive check to that workflow.

Review backups and prove the controls still work

Backups can contain configuration files, cached configuration, and encryption keys. Restrict access to those archives, protect their encryption keys separately, and confirm that authorized responders can recover what the application needs.

After deployment changes, check that:

  • Public routes cannot return private configuration or backup files.
  • Only intended identities can read each application's secrets.
  • Logs and release artifacts omit live credentials.
  • All consumers can adopt replacement credentials, and retired credentials are rejected.
  • A recovery exercise restores the application without exposing secrets in its output.

Record results and responsible owners. Pair this review with the VPS security baseline. When evaluating Core Panel, use its security information and current documentation to verify relevant controls. Core Panel is currently pre-production; evaluate it on an isolated non-production server.

Frequently asked questions

Is a .env file encrypted?

A typical .env file is plaintext. Its name does not provide encryption or access control. Protect its location, permissions, copies, and the processes that read it.

Is chmod 600 enough to secure .env?

It restricts ordinary file permissions to the owner, but ownership, shared service identities, directory access, and other access mechanisms still matter. It does not protect against a compromised process already authorized to read the file.

Can I fix a leaked API key by deleting the file?

No. Revoke or replace the key with its issuer and update legitimate consumers. Removing the exposed copy does not invalidate copies someone may already hold.

Should I regenerate APP_KEY after every deployment?

No. Application encryption keys protect existing data and may affect sessions. Change them through a deliberate, tested rotation or incident-response procedure.

Related posts

Stay in the loop

New posts and release notes, delivered to your inbox. No spam.

Ready to switch?
14-day free trial
Get Started