When managing multiple Linux servers (in this case 20), documenting configurations becomes crucial for maintenance, security compliance, and team collaboration. While configuration files contain all the data, they're scattered across systems making centralized documentation essential.
Here are the main approaches with their pros and cons:
1. Spreadsheet (Quick but limited)
- Pros: Easy to start, universally accessible
- Cons: Hard to maintain, no version control, limited search
2. Database-backed Web App (More robust)
- Pros: Structured data, access control, searchable
- Cons: Requires development/maintenance
3. Configuration Management Tools (Most scalable)
- Pros: Automated, version controlled
- Cons: Learning curve, may be overkill
For those preferring a custom web solution, here's a basic schema and code example:
CREATE TABLE server_configs (
id int(11) NOT NULL AUTO_INCREMENT,
hostname varchar(255) NOT NULL,
ip_address varchar(15) NOT NULL,
ssh_port int(5) DEFAULT 22,
physical_location text,
last_updated timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id)
);
CREATE TABLE server_users (
id int(11) NOT NULL AUTO_INCREMENT,
server_id int(11) NOT NULL,
username varchar(32) NOT NULL,
uid int(11) DEFAULT NULL,
shell varchar(255) DEFAULT NULL,
PRIMARY KEY (id),
FOREIGN KEY (server_id) REFERENCES server_configs(id)
);
To gather data automatically, consider this bash script that outputs CSV for import:
#!/bin/bash
echo "Hostname,IP,SSH Port,Users Count"
for server in $(cat server_list.txt); do
users=$(ssh $server "grep -c '/bin/bash' /etc/passwd")
ip=$(host $server | awk '{print $4}')
echo "$server,$ip,22,$users"
done
- Ansible: Can generate facts inventory
- NetBox: IPAM and DCIM with API
- phpIPAM: Open source IP address management
- RackTables: Datacenter asset management
Whatever solution you choose, integrate it with Git for change tracking:
# Sample Git workflow
git init
git add server_docs.csv
git commit -m "Initial server configuration import"
git tag -a v1.0 -m "Baseline configuration"
Managing multiple Linux servers (in this case 20) requires systematic documentation of critical configuration elements. While configuration files store this data natively, accessing it across servers becomes inefficient during audits, troubleshooting, or handovers.
While spreadsheets offer quick documentation, they present several limitations:
- No version control or change tracking
- Difficult to maintain consistency across multiple editors
- Limited data validation capabilities
- Poor handling of relational data (e.g., user-database permissions)
Option 1: Configuration Management Database (CMDB)
A lightweight CMDB solution like Ralph
or iTop
provides structured data storage:
# Example Ralph API call to document a server
curl -X POST https://cmdb.example.com/api/assets \\
-H "Authorization: Token yourtoken" \\
-H "Content-Type: application/json" \\
-d '{
"hostname": "web01",
"ip_addresses": ["192.168.1.10"],
"ssh_port": 2222,
"location": "Rack A-12",
"users": ["admin", "deploy"],
"databases": [
{
"name": "app_db",
"users": [
{"name": "app_user", "permissions": "SELECT,INSERT"}
]
}
]
}'
Option 2: Infrastructure as Code (IaC) Approach
Combine Ansible facts with custom documentation modules:
# ansible-document.yml
- hosts: all
gather_facts: yes
tasks:
- name: Document server configuration
template:
src: documentation_template.j2
dest: "/var/docs/{{ inventory_hostname }}.md"
- name: Centralize documentation
synchronize:
src: "/var/docs/"
dest: "~/server_docs/"
delegate_to: localhost
Option 3: Custom PHP/MySQL Solution
For teams preferring in-house tools, a simple CRUD application can be implemented:
// database schema example
CREATE TABLE servers (
id INT AUTO_INCREMENT PRIMARY KEY,
hostname VARCHAR(255) UNIQUE,
ip_address VARCHAR(15),
ssh_port INT DEFAULT 22,
location TEXT
);
CREATE TABLE server_users (
id INT AUTO_INCREMENT PRIMARY KEY,
server_id INT,
username VARCHAR(32),
FOREIGN KEY (server_id) REFERENCES servers(id)
);
// API endpoint example
$app->get('/api/servers/{hostname}', function ($request, $response, $args) {
$server = $this->db->query(
"SELECT * FROM servers WHERE hostname = ?",
[$args['hostname']]
)->fetch();
if (!$server) {
return $response->withStatus(404);
}
$users = $this->db->query(
"SELECT username FROM server_users WHERE server_id = ?",
[$server['id']]
)->fetchAll();
return $response->withJson([
'server' => $server,
'users' => $users
]);
});
Consider implementing these automated documentation workflows:
#!/bin/bash
# Automated documentation script
for server in $(cat server.list); do
ssh -p 2222 admin@$server <<'ENDSSH'
echo "=== $HOSTNAME ==="
echo "IP: $(hostname -I)"
echo "Users: $(getent passwd | grep -v /bin/false | cut -d: -f1)"
mysql -e "SELECT User,Host FROM mysql.user" 2>/dev/null
ENDSSH
done | tee server_docs_$(date +%F).txt
When implementing any documentation solution:
- Encrypt sensitive data (database credentials)
- Implement proper access controls
- Regularly audit documentation access
- Consider using Vault for credential storage
To keep documentation accurate:
- Integrate with provisioning systems (Terraform, Puppet)
- Set up change hooks to trigger documentation updates
- Schedule regular verification audits
- Include documentation in your CI/CD pipeline