Fly.io applications can’t store secrets directly in your Git repository or your application code.
Let’s say you have a database password or an API key that your application needs to authenticate with an external service. Storing this sensitive information directly in your code or configuration files that get committed to source control is a huge security risk. Anyone who can access your repository would have your secrets. Fly.io provides a secure way to manage these secrets and inject them into your running application.
Here’s how it works, and how you can use it.
The Secret is the Key
Fly.io treats secrets as key-value pairs associated with your application. When your application starts, Fly.io injects these key-value pairs as environment variables. Your application code then reads these environment variables to get the secret values.
Let’s set up a simple example. Imagine you have a Node.js application that needs a DATABASE_URL.
First, ensure you have the Fly.io CLI installed and are logged in.
fly auth login
Now, let’s create a new Fly.io application if you don’t have one already.
fly apps create my-secret-app
You’ll need a fly.toml file in your project directory. For a simple Node.js app, it might look like this:
app = "my-secret-app"
primary_region = "ord"
[build]
builder = "heroku/buildpacks"
[deploy]
strategy = "all"
Now, let’s add a secret. We’ll use the fly secrets command. The syntax is fly secrets set KEY=VALUE --app APP_NAME.
fly secrets set DATABASE_URL="postgres://user:password@host:port/dbname" --app my-secret-app
This command tells Fly.io to store the DATABASE_URL secret for your my-secret-app. If you run this command again with the same key, it will update the existing secret.
You can also list your secrets to verify.
fly secrets list --app my-secret-app
This will show you the keys of the secrets you’ve set, but not their values, for security.
Injecting Secrets into Your App
When your application deploys and starts on Fly.io, the secrets you’ve set are automatically available as environment variables.
For our Node.js example, in your application code (e.g., index.js), you would access it like this:
const databaseUrl = process.env.DATABASE_URL;
if (!databaseUrl) {
console.error("DATABASE_URL environment variable is not set!");
process.exit(1);
}
console.log("Successfully retrieved DATABASE_URL from environment.");
// Now use databaseUrl to connect to your database
When you deploy your application, Fly.io handles the injection.
fly deploy --app my-secret-app
After deployment, if you check the logs for your app, you should see:
Successfully retrieved DATABASE_URL from environment.
This confirms that the secret was successfully injected and read by your application.
Managing Secrets with fly.toml (Advanced)
While fly secrets set is the primary way to manage secrets, you can also declare secrets directly in your fly.toml file. This is useful for ensuring secrets are present for a new deployment or for managing secrets that are not directly sensitive, like configuration flags that you don’t want to hardcode.
app = "my-secret-app"
primary_region = "ord"
[build]
builder = "heroku/buildpacks"
[deploy]
strategy = "all"
[env]
ANOTHER_SECRET = "some-other-value"
# You can also reference secrets that are *already set* on Fly.io
# EXTERNAL_API_KEY = "fly_secret_api_key_name_on_flyio" # This is less common and more complex
Using [env] in fly.toml for values that are not sensitive is fine. However, for actual secrets like passwords or API keys, the recommended and secure method is always fly secrets set. The fly secrets command encrypts and stores these values securely on Fly.io’s infrastructure, separate from your application’s code and configuration files.
If you set a secret in fly.toml that already exists via fly secrets set, the value set via fly secrets set will take precedence.
Why This is Secure
The core security benefit here is that your sensitive credentials never touch your Git repository. They are stored encrypted on Fly.io’s systems. When your application starts, Fly.io decrypts them and provides them to your application’s environment. This isolation is crucial for maintaining the security of your application’s credentials.
Furthermore, you can manage who has access to set or view secrets through Fly.io’s team and role management features, adding another layer of security and control.
The next step you’ll likely encounter is managing secrets for different environments (e.g., staging vs. production) or rotating secrets when they are compromised or expire.