How to Rotate API Keys Automatically on Ubuntu with Python

Published 2026-09-05 · How-to

Understanding API Key Rotation and Its Importance

To maintain the security and integrity of your applications, it's crucial to rotate API keys regularly. This practice helps prevent unauthorized access in case a key is compromised. API key rotation involves generating a new key, updating it in your application, and securely storing the new key. This process can be manual, but automating it ensures consistency and reduces the risk of human error.

The key components of API key rotation include key generation, storage, and scheduling. Key generation involves creating a new, unique API key, while storage requires securing the key to prevent unauthorized access. Scheduling is critical for automating the rotation process.

import os
import secrets
import string

def generate_api_key(length=32):
    """Generate a random API key"""
    characters = string.ascii_letters + string.digits
    return ''.join(secrets.choice(characters) for _ in range(length))

# Example usage:
new_key = generate_api_key()
print(new_key)

By automating API key rotation, you can ensure that your keys are updated regularly, reducing the risk of a security breach. The next steps will outline how to implement this automation using Python and Ubuntu's cron jobs.

Prerequisites: Ubuntu Setup and Python Installation

Before diving into the automation of API key rotation, it's essential to have a solid foundation. This includes setting up Ubuntu and installing Python. Ubuntu is a popular choice for servers due to its stability and security features. For this tutorial, ensure you have a recent version of Ubuntu installed.

To install Python, you can use the package manager. Python 3 is the default version in recent Ubuntu releases, but it's good practice to specify the version to ensure compatibility. You can install Python 3 and pip (the package installer for Python) by running:

sudo apt update
sudo apt install python3 python3-pip
Additionally, you'll need to install any libraries required for your API interactions. The specific libraries will depend on the APIs you're working with, but requests is a common choice for making HTTP requests in Python. You can install it using pip:
pip3 install requests
Ensure your Ubuntu system is up to date and that you have the necessary permissions to install software and manage system services like cron jobs. With Ubuntu set up and Python installed, you're ready to start building your API key rotation script.

Writing a Python Script to Generate and Update API Keys

The process of generating and updating API keys can be efficiently managed with a Python script. This script should be designed to create new keys, update existing ones, and handle the storage of these keys securely. For secure storage, utilizing environment variables on Ubuntu is a practical approach.

To start, you'll need to install the necessary Python libraries. The python-dotenv library is useful for handling environment variables, and requests can be used for interacting with APIs. You can install these libraries using pip:

pip install python-dotenv requests
A basic script structure would involve loading existing keys from environment variables, generating new keys, and then updating the environment variables with the new keys. This can be achieved with a simple Python script that utilizes these libraries to handle the key rotation logic.

Here's a simple example of how you might structure the key generation and update part of your script:

import os
import dotenv
import requests

# Load environment variables
dotenv.load_dotenv()

# Generate new API key
new_key = requests.post('https://example.com/generate-api-key').text

# Update environment variable with new key
os.environ['API_KEY'] = new_key
This example assumes an API endpoint for generating new keys, which you would replace with your actual API endpoint. The script loads the current environment variables, generates a new API key by making a POST request to the specified endpoint, and then updates the API_KEY environment variable with the newly generated key.

Securely Storing New API Keys with Environment Variables

To securely store new API keys, utilizing environment variables is a recommended approach. This method keeps sensitive information out of your codebase, reducing the risk of exposure. On Ubuntu, you can set environment variables in your shell configuration files or use a dedicated secrets management tool.

For simplicity and effectiveness, you can store your API keys as environment variables directly in your system. Here's how you can do it:

export API_KEY="your_new_api_key_here"
However, for a more persistent solution that survives shell restarts, you should add these variables to your shell configuration file, typically ~/.bashrc or ~/.profile, depending on your shell.

When working with Python scripts, accessing these environment variables can be done using the os module. A basic example of how to retrieve and use an environment variable in Python is shown below, but for the purpose of this tutorial, we'll focus on securely storing and rotating the keys.

A better approach for managing API keys involves using a secrets manager or encrypting the keys. However, for the scope of this tutorial, we'll keep the focus on basic environment variable usage for simplicity.

Environment VariableDescription
API_KEYThe current API key in use
API_KEY_EXPIRYTimestamp for when the API key expires

Automating the Rotation Process Using Cron Jobs

First, place the rotation script in a dedicated directory so it can be referenced reliably. A common layout is /opt/api‑key‑rotator/rotate.py and a log file at /var/log/api‑key‑rotator.log. Make the script executable and restrict access:

sudo mkdir -p /opt/api-key-rotator
sudo cp rotate.py /opt/api-key-rotator/
sudo chmod 750 /opt/api-key-rotator/rotate.py
sudo chown root:root /opt/api-key-rotator/rotate.py
sudo touch /var/log/api-key-rotator.log
sudo chmod 640 /var/log/api-key-rotator.log
sudo chown root:adm /var/log/api-key-rotator.log

Next, edit the root crontab (or a dedicated service account) to run the script at the desired interval. For a daily rotation at 02:30 UTC:

sudo crontab -e

Add the line:

30 2 * * * /usr/bin/python3 /opt/api-key-rotator/rotate.py >> /var/log/api-key-rotator.log 2>&1

A few practical tips:

IssueCron‑friendly solution
Environment varsSource a wrapper that exports needed vars before running the script.
Overlapping runsPrefix the command with flock -n /tmp/rotate.lock to prevent concurrent executions.
Notification on failureAppend </td><td></td><td>echo "Rotation failed"</td><td>mail -s "API key rotation error" admin@example.com
Putting it together, a robust entry looks like:

30 2 * * * flock -n /tmp/rotate.lock /usr/bin/python3 /opt/api-key-rotator/rotate.py >> /var/log/api-key-rotator.log 2>&1 || echo "Rotation failed" | mail -s "API key rotation error" admin@example.com

After saving, verify the schedule with sudo crontab -l. Test the job immediately by running the command manually; if the log updates and the new key appears where your application expects it, the cron‑driven automation is ready. Remember to reload systemd’s journal (sudo systemctl restart cron) if you modify the crontab while the daemon is already running.

Testing the Automated Rotation and Verifying Functionality

Run the rotation script once manually and watch its exit code, log file, and the environment file that stores the new secret. A clean run should end with 0, append a timestamped line to /var/log/api‑rotate.log, and replace the old value in ~/.api_key.env.

# Execute the script
sudo /usr/local/bin/rotate_api_key.py
# Verify exit status
echo "Exit code: $?"
# Inspect the log
tail -n 3 /var/log/api-rotate.log
# Show the stored key (redacted for safety)
grep API_KEY ~/.api_key.env

If any step fails, the script writes a detailed error to the same log and exits with a non‑zero code. Add a quick sanity check that the dependent service can still authenticate:

import os, requests

key = os.getenv("API_KEY")
resp = requests.get("https://api.example.com/health", headers={"Authorization": f"Bearer {key}"})
print("Health check:", resp.status_code)

Save this as check_api.py and run it after rotation; a 200 response confirms the new key works.

CheckExpected result
Script exit code0
Log entryYYYY‑MM‑DD HH:MM:SS – rotated
~/.api_key.env lineAPI_KEY=<new‑value>
Health‑check status200
Finally, trigger the cron job manually to ensure scheduling works:

sudo systemctl restart cron
sudo run-parts --test /etc/cron.d

If the log shows a new entry and the health check passes, the automated rotation is verified and ready for production.

Error Handling, Logging, and Monitoring

A robust script must survive network hiccups, permission errors, and malformed responses without leaving stale credentials on the system. Wrap every external call—HTTP requests, file writes, and subprocess invocations—in try/except blocks and surface a clear exit code so the scheduler can react appropriately.

import logging, sys, requests, os
from pathlib import Path

LOG_FILE = "/var/log/api_key_rotator.log"
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s %(levelname)s %(message)s",
    handlers=[
        logging.FileHandler(LOG_FILE),
        logging.StreamHandler(sys.stdout),
    ],
)

def fetch_new_key():
    try:
        resp = requests.get("https://example.com/new-key", timeout=10)
        resp.raise_for_status()
        return resp.json()["key"]
    except requests.RequestException as e:
        logging.error("Failed to obtain new key: %s", e)
        sys.exit(1)

def write_key(key):
    try:
        env_path = Path("/etc/profile.d/api_key.sh")
        env_path.write_text(f'export API_KEY="{key}"\n')
        os.chmod(env_path, 0o600)
        logging.info("Wrote new key to %s", env_path)
    except OSError as e:
        logging.error("Unable to write key file: %s", e)
        sys.exit(2)

if __name__ == "__main__":
    new_key = fetch_new_key()
    write_key(new_key)
    logging.info("API key rotation completed successfully")

LevelWhen to use
DEBUGVerbose output for development; disable in production.
INFONormal operation messages (key written, rotation started).
WARNINGRecoverable issues (e.g., temporary API throttling).
ERRORNon‑recoverable failures that abort the run.
CRITICALSystem‑wide problems (disk full, permission loss).
Cron can email the log on failure (MAILTO=user@example.com) or you can pipe the log to a monitoring agent like Prometheus node‑exporter. By exiting with distinct codes (1 = fetch error, 2 = write error), you enable automated alerts and quick triage without manual log inspection.

FAQ

How can I automate API key rotation on Ubuntu using cron?

To automate API key rotation on Ubuntu, write a shell or Python script that calls the provider’s key‑creation endpoint, stores the new key securely (e.g., in a vault or encrypted file), and updates any configuration files or environment variables used by your services. Then add a cron entry (crontab -e) that runs the script at your desired interval, such as `0 2 * * 0` for weekly rotation. Make sure the script logs success or failure and has appropriate permissions to avoid exposing the keys.

What is a safe way to store rotated API keys for a Python application?

Store rotated API keys in a location that your Python code can read at runtime but that is not checked into source control. Common solutions include HashiCorp Vault, AWS Secrets Manager, Azure Key Vault, or an encrypted file decrypted by a startup script. In your application, load the secret using a library (e.g., python‑dotenv, hvac for Vault) and inject it into the client configuration. Rotate the secret in the vault, then reload or restart the process so it picks up the new value, keeping the old key revoked.

How do I script the generation of a new API key and update environment variables?

Create a script (bash, Python, or PowerShell) that first calls the service’s API to generate a new key, captures the returned token, and writes it to a secure store. Then replace the old key in the target environment – for example, update a `.env` file, a Kubernetes secret, or an AWS Parameter Store entry – and optionally trigger a reload of the affected services. Finally, revoke the previous key using the provider’s revoke endpoint to ensure it can no longer be used.

Can I rotate API keys without downtime for a service that uses them?

To rotate API keys without causing downtime, use a rolling update strategy. First, generate the new key and add it alongside the existing one if the service supports multiple concurrent keys. Update your configuration to include both keys, then restart or reload a subset of instances so they start using the new key while the old one remains valid. Once all instances have successfully switched, remove the old key from the configuration and revoke it via the provider’s API. This approach ensures that at any moment at least one valid key is available, preventing service interruption.

What are best practices for logging and monitoring API key rotation?

Logging and monitoring are essential for reliable API key rotation. Emit structured logs each time a rotation script runs, including timestamps, success/failure status, and the identifier of the new key (never the secret itself). Forward these logs to a central system like ELK, Splunk, or CloudWatch. Set up alerts on failure events or on unusually frequent rotations, which may indicate a breach. Additionally, track key usage metrics from the provider’s dashboard to verify that the old key is no longer being called after revocation.

Related reading