Linux Security·7 min read·

Managing Secrets on a VPS: Permissions, Env, Vault

Store API keys and tokens safely on a Linux VPS with strict file permissions, protected environment files, and vault basics that survive a leak.

NB

Netbay Developer Relations

Netbay Engineering

On this page

Secrets are the quiet failure of most VPS setups. A database password hardcoded in a config file, an API key pasted into a shell history, a .env file nudged to 0644 so a monitoring script could read it — any of these leaks quietly becomes the compromise you find out about at ransom time. This guide covers the practical layers of secret management on a Linux server: where secrets can live, how to protect them with the filesystem, and when to reach for a vault. None of it requires exotic tooling; it requires treating keys as the credentials they are.

Keeping secrets out of the wrong hands FILESYSTEM owner + mode 600 protected .env no 0777 templates ENVIRONMENT env not hardcoded no shell history rotated on leak VAULT encrypted at rest audit trails machine identity Each layer reduces where a secret can live and how far a leak travels

The Baseline: Filesystem Permissions Done Right

Most secrets on a single VPS live in a file, so the filesystem is the first and most important defense. A secret file must be owned by the account that needs it and readable by nothing else. The classic mistakes — a repository with a .env committed to git, a 664 group-readable config, or a backup uploaded with tightened permissions — all collapse if you enforce ownership and mode on the source of truth. On a Linux box, mode 600 on a file owned by the service account is the whole differential between exposed and contained.

bash
sudo install -o www-data -g www-data -m 600 /etc/app/.env /etc/app/.env
sudo chmod 700 /etc/app
sudo git check-ignore .env

The install command sets owner, group, and mode atomically, so there is no window where the file is world-readable during the copy. The chmod on the containing directory keeps listing and traversal limited. And git check-ignore confirms your pattern — .env in .gitignore — is actually active, because the number-one leak vector is a secret accidentally committed in the first place. Get those three right and you have already prevented more leaks than any vault.

Environment Files You Control, Not Config You Trust

Environment variables are the standard way to hand secrets to an application without baking them into source. The trick is that loading them must be a deliberate, permission-guarded step — not a shell snippet you run and lose. Load a protected .env from your service unit or orchestration tool at startup so the secret is only ever in memory and in the one file you own.

bash
set -a
source /etc/app/.env
set +a
sudo systemctl show myapp -p EnvironmentFiles

set -a exports every variable from the sourced file, and set +a stops the export from leaking beyond this command. On systemd systems, point the unit's EnvironmentFile at the protected path and let the service manager load it, so the secret never touches a shell you cannot audit. Whatever mechanism you choose, the file stays at 600 and the secret stays out of git, out of the command line, and out of shell history.

Never Put Secrets on the Command Line

Shell history is a secondary leak you usually do not even see until it is quoted back at you. Databases accept a -p option that reads the password from the command line, and that value lands in ~/.bash_history and in /proc/pid/cmdline for every concurrent process to read. The fix is to feed credentials through files or the environment instead of arguments.

bash
export PGPASSWORD="$(< /etc/app/.env.pg)"
psql -h db.internal -U app -d appdb -c "select 1"
unset PGPASSWORD

The export reads the password from a protected file into the environment for the duration of the command, then unset clears it. Tools like mysqldump and pg_dump honor such an environment variable instead of a visible argument. Auditing cmdline is one of the first things an attacker does after breaching a box, and empty cmdline secrets are a habit that costs nothing to build.

Rotate, and Rotate When You Suspect a Leak

No amount of careful storage helps if a secret is already in the wild. Rotation is the backstop: assume every API key and every long-lived password will eventually leak, and architect so that rotating one does not cascade. Store each credential in its own place, keep their lifetimes short where a provider allows it, and flip credentials the moment you see any sign of exposure — an unexpected login, a token in a log line, a repo that was briefly public.

bash
aws secretsmanager create-secret --name prod/api/db --secret-string "postgres://app:NEWPW@db/app"
systemctl reload myapp

Bring-your-own tools work the same way: a script that generates a fresh random password, writes it to the protected file, and reloads the service. The requirement is that rotation is mechanical and repeatable, never a manual Friday-afternoon paste. If rotation feels hard, that is a signal your secret layout is too entwined, and the fix is to decouple before you need it.

When a Vault Is Worth the Complexity

At some point — multiple services, shared credentials, a growing team — a dedicated vault earns its keep. Vaults store secrets encrypted at rest, hand them out just-in-time with short leases, and log every read, which gives you an audit trail a flat file can never provide. The cost is real operational weight: you must run the vault, manage its unseal and high-availability story, and give each workload a way to authenticate. For a handful of boxes, that cost usually exceeds the benefit. The line is crossed when you start asking "who read this secret and when" and cannot answer from filesystem metadata alone.

When you do introduce a vault, keep the same discipline: the vault itself is a secret that must be protected, and the machine identity it trusts is a credential in its own right. Start with permissions and env hygiene — they solve the majority of real-world leaks — and treat a vault as the next step only when the operational cost is justified by the threat you face.

Takeaway

Secret management on a VPS is mostly discipline before it is tooling: strict file ownership and mode, environment files loaded deliberately, secrets never on the command line, and rotation that is mechanical. Add a vault when you genuinely need audit and just-in-time delivery, not before. A Netbay Ubuntu VPS gives you full control of the filesystem from the first boot, so you can build this secret hygiene in from the start — netbayhosts.in.

Keep reading

Follow along on a real VPS

Deploy Linux in under 60 seconds

These guides are written against Ubuntu, Debian, and RHEL-family images — the same ones on NetBay.

Deploy an instance