Automating Linux User Lifecycle with GitHub Actions: A Practical DevOps Guide

https://abhaypatil001.github.io/abhay-portfolio/
Search for a command to run...

https://abhaypatil001.github.io/abhay-portfolio/
No comments yet. Be the first to comment.
Managing sensitive credentials like API keys across multiple GitHub repositories is challenging. It leads to duplicate secrets, a lack of versioning, and potential inconsistencies between environments. The solution is to use HashiCorp Vault Secrets o...

Introduction DevOps engineers today spend countless hours context-switching between dashboards, logs, cloud consoles, and documentation. Traditional AI tools like ChatGPT are great at answering questions, but they lack direct access to your infrastru...

When working with GitHub Actions, you may face situations where multiple workflow runs overlap, consume unnecessary resources, or even cause conflicts in deployment. This is where concurrency comes into play. Concurrency in GitHub Actions allows you ...

When teams scale, managing workflows across multiple repositories becomes more complex. Each project often shares common configuration values, cloud credentials, or deployment secrets. Instead of duplicating these across repositories, GitHub provides...

CloudDecode
11 posts
CloudDecode simplifies cloud & DevOps—covering Azure, AWS, Kubernetes, Terraform, CI/CD & more—with clear guides to help you decode, learn, and build with confidence.
User access management is one of the most fundamental responsibilities in any infrastructure environment, yet it is often handled in an ad hoc and manual way. In many organizations, especially during rapid development cycles, access is granted quickly but rarely reviewed or revoked with the same rigor.
Developers, vendors, and support engineers frequently require temporary access to systems. While the intention is short-term access, the implementation often becomes long-term exposure.
This article walks through a practical approach to solving this problem using GitHub Actions, starting from basic concepts and moving toward a production-ready automation pattern.
In a typical environment, user access is managed manually through system administrators. A request comes in, a user is created, and access is granted. However, several issues arise with this approach:
There is no standard mechanism to enforce access duration
Users are often not removed after their task is completed
There is limited or no audit trail of who created the user and why
Access reviews are either infrequent or non-existent
Security policies like least privilege are not consistently followed
Consider a simple command:
sudo useradd ammar
This creates a user with no expiry. Unless someone explicitly removes this user later, the account remains active indefinitely.
Over time, this leads to:
Accumulation of unused accounts
Increased attack surface
Compliance and audit failures
Difficulty in tracking ownership of accounts
This is not a tooling problem; it is a process and automation problem.
The goal is to build a system that:
Creates users in a controlled and repeatable manner
Enforces an expiry date at the time of creation
Provides traceability through pipeline logs
Reduces manual intervention
Aligns with security best practices
Linux provides a built-in way to set an account expiry date at the time of user creation.
sudo useradd -e 2026-12-07 ammar
This ensures that the account becomes inactive automatically after the specified date.
To verify:
sudo chage -l ammar
This command shows account expiry and password aging details.
This is a simple but powerful feature that is often underutilized.
Instead of creating users manually, we automate the process using a CI/CD pipeline.
The high-level flow looks like this:
A request is made to create a user (username + expiry date)
A GitHub Actions workflow is triggered
The workflow connects to the target server via SSH
A script runs to create the user with the specified expiry
Logs are stored in the pipeline for auditing
This approach ensures consistency, repeatability, and visibility.
Create a repository with the following structure:
user-access-automation/
├── .github/workflows/
│ └── create-user.yml
├── scripts/
│ └── create_user.sh
└── README.md
This script handles user creation logic.
#!/bin/bash
set -e
USERNAME=$1
EXPIRY_DATE=$2
if [[ -z "\(USERNAME" || -z "\)EXPIRY_DATE" ]]; then
echo "Usage: $0 <username> <expiry_date>"
exit 1
fi
echo "Creating user: $USERNAME"
echo "Expiry date: $EXPIRY_DATE"
sudo useradd -m -e "\(EXPIRY_DATE" "\)USERNAME"
PASSWORD=$(openssl rand -base64 12)
echo "\(USERNAME:\)PASSWORD" | sudo chpasswd
sudo chage -d 0 "$USERNAME"
sudo chage -l "$USERNAME"
name: Create Temporary User
on:
workflow_dispatch:
inputs:
username:
description: "Enter username"
required: true
expiry_date:
description: "Expiry date (YYYY-MM-DD)"
required: true
jobs:
create-user:
runs-on: ubuntu-latest
steps:
- name: Create user via SSH
uses: appleboy/ssh-action@v1.0.0
with:
host: ${{ secrets.SERVER_IP }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
sudo useradd -m -e "\({{ github.event.inputs.expiry_date }}" "\){{ github.event.inputs.username }}"
sudo chage -l "${{ github.event.inputs.username }}"
In your GitHub repository:
Settings → Secrets and variables → Actions
Add:
SERVER_IP
SERVER_USER
SSH_PRIVATE_KEY
These values are injected securely during workflow execution.
Navigate to the Actions tab
Select the workflow
Click "Run workflow"
Provide username and expiry date
The user will be created on the target server with the defined expiry.
You can test the script directly on a GitHub-hosted runner:
runs-on: ubuntu-latest
However, this only validates the logic because the runner is temporary. Any user created there will be removed once the job completes.
For real testing, always validate on a target server via SSH.
Use SSH key-based authentication instead of passwords
Avoid direct root login; use a controlled sudo user
Use non-interactive shells for service accounts when applicable
Store all sensitive data in GitHub Secrets
Implement approval gates for production workflows
Once the basic system is working, you can extend it further:
Schedule a job to remove expired users automatically
Integrate approval workflows using GitHub Environments
Add logging to centralized systems like ELK or Azure Monitor
Replace raw SSH execution with configuration management tools like Ansible
Introduce role-based access control for different environments
This approach provides:
Consistent and repeatable user provisioning
Reduced operational overhead
Improved auditability
Better alignment with security policies
It also demonstrates a mature DevOps mindset where manual processes are systematically replaced with controlled automation.
User access management is often treated as a routine administrative task, but it has significant security implications. By introducing automation with expiry enforcement, you can reduce risk and improve operational efficiency.
The solution described here is simple to implement but scalable enough to be extended into enterprise-grade workflows.
Abhay Patil DevOps Engineer
Blog: https://clouddecode.in LinkedIn: https://www.linkedin.com/in/abhay-patil-devops/
Automating small operational tasks like user management can have a significant impact on overall system security and reliability.