Skip to content

Commit aab4279

Browse files
authored
Update README.md to enhance documentation structure and clarity, including detailed features, configuration instructions, and usage examples for the SSH Key Sync script. (#13)
1 parent 3412528 commit aab4279

File tree

1 file changed

+258
-49
lines changed

1 file changed

+258
-49
lines changed

README.md

Lines changed: 258 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,83 +1,292 @@
1-
# SSH Key Sync Script
1+
# SSH Key Sync
22

3-
This Bash script pulls `authorized_keys` files from remote URLs and updates SSH access for multiple local users.
3+
[![Lint Status](https://img.shields.io/github/actions/workflow/status/locus313/ssh-key-sync/lint.yml?style=flat-square&label=lint)](https://github.com/locus313/ssh-key-sync/actions)
4+
[![License](https://img.shields.io/badge/License-MIT-blue?style=flat-square)](LICENSE)
5+
[![Shell](https://img.shields.io/badge/Shell-Bash-green?style=flat-square&logo=gnu-bash)](https://www.gnu.org/software/bash/)
6+
[![Version](https://img.shields.io/badge/Version-0.1.0-orange?style=flat-square)](https://github.com/locus313/ssh-key-sync/releases)
47

5-
## 🔧 Features
8+
⭐ If you like this project, star it on GitHub — it helps a lot!
69

7-
- Pull-based (ideal for cron or systemd timer)
8-
- Supports multiple users
9-
- Works with:
10-
- ✅ Public URLs (method: `raw`)
11-
- ✅ Private GitHub repositories via GitHub API (method: `api`, requires token)
12-
- ✅ GitHub user public keys (method: `ghuser`)
13-
- Safe: Only updates keys if they’ve changed
14-
- Logs activity per user
15-
- Retries failed fetch operations up to 3 times with a delay
16-
- **Self-update**: Automatically updates the script to the latest version from the GitHub repository
10+
[Features](#features)[Getting Started](#getting-started)[Configuration](#configuration)[Usage](#usage)[Examples](#examples)[Automation](#automation)
1711

18-
## ⚙️ Configuration
12+
A robust Bash script for automating SSH `authorized_keys` synchronization across multiple users from various sources. Perfect for managing SSH access in development environments, CI/CD pipelines, and production systems.
1913

20-
User configuration is stored in a separate `users.conf` file in the same directory as the script.
21-
Edit `users.conf` to define users and their key sources.
22-
Each entry uses the format:
23-
`["username"]="method:url"`
14+
## Features
2415

25-
- **raw:** Fetches directly from a public URL.
26-
- **api:** Fetches from a private GitHub repo using the GitHub API (requires `GITHUB_TOKEN` environment variable).
27-
- **ghuser:** Fetches public keys from a GitHub user's profile (provide the GitHub username after the colon).
16+
- **Multiple Key Sources**: Fetch SSH keys from public URLs, private GitHub repositories, or GitHub user profiles
17+
- **Retry Logic**: Built-in retry mechanism with configurable delays for handling network failures
18+
- **Safe Updates**: Only modifies `authorized_keys` when remote content has actually changed
19+
- **Comprehensive Logging**: Detailed timestamped logs for monitoring and debugging
20+
- **Self-Updating**: Automatically update to the latest version from the GitHub repository
21+
- **Configuration-Driven**: External configuration file for easy management
22+
- **Error Handling**: Robust error handling with graceful fallbacks
23+
- **Multi-User Support**: Manage SSH keys for multiple system users simultaneously
2824

29-
You can also set your GitHub token in the config file using `CONF_GITHUB_TOKEN`.
30-
If `GITHUB_TOKEN` is not set in the environment, the script will use `CONF_GITHUB_TOKEN` from `users.conf`.
25+
## Getting Started
26+
27+
### Prerequisites
28+
29+
- Bash 4.0 or later
30+
- `curl` for HTTP requests
31+
- `getent` for user information (typically available on Linux systems)
32+
- GitHub token (only required for private repository access)
33+
34+
### Quick Start
35+
36+
1. **Download the script**:
37+
```bash
38+
curl -fsSL https://raw.githubusercontent.com/locus313/ssh-key-sync/main/sync-ssh-keys.sh -o sync-ssh-keys.sh
39+
chmod +x sync-ssh-keys.sh
40+
```
41+
42+
2. **Download the configuration template**:
43+
```bash
44+
curl -fsSL https://raw.githubusercontent.com/locus313/ssh-key-sync/main/users.conf -o users.conf
45+
```
46+
47+
3. **Configure your users** by editing `users.conf`:
48+
```bash
49+
nano users.conf
50+
```
51+
52+
4. **Run the script**:
53+
```bash
54+
./sync-ssh-keys.sh
55+
```
56+
57+
## Configuration
58+
59+
Configuration is managed through the `users.conf` file, which defines users and their SSH key sources.
60+
61+
### Configuration Format
3162

32-
**Example `users.conf`:**
3363
```bash
64+
# Optional: GitHub token for private repository access
3465
CONF_GITHUB_TOKEN="your_github_token_here"
3566

67+
# User key mapping
68+
declare -A USER_KEYS=(
69+
["username"]="method:target"
70+
)
71+
```
72+
73+
### Supported Methods
74+
75+
| Method | Description | Example |
76+
|--------|-------------|---------|
77+
| `raw` | Fetch from public URL | `raw:https://example.com/keys.txt` |
78+
| `api` | Fetch from private GitHub repo via API | `api:https://api.github.com/repos/org/repo/contents/keys/user.keys?ref=main` |
79+
| `ghuser` | Fetch public keys from GitHub user | `ghuser:username` |
80+
81+
### Example Configuration
82+
83+
```bash
84+
#!/bin/bash
85+
86+
# GitHub token for API access (optional)
87+
CONF_GITHUB_TOKEN="ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
88+
89+
# User key definitions
3690
declare -A USER_KEYS=(
91+
# Fetch from public URL
3792
["ubuntu"]="raw:https://example.com/ssh-keys/ubuntu.authorized_keys"
93+
94+
# Fetch from private GitHub repository
3895
["devuser"]="api:https://api.github.com/repos/yourorg/ssh-keys/contents/keys/devuser.authorized_keys?ref=main"
96+
97+
# Fetch public keys from GitHub user
3998
["alice"]="ghuser:alice-github-username"
99+
["bob"]="ghuser:bob-github-username"
40100
)
41101
```
42102

43103
## Usage
44104

45-
1. Edit the `users.conf` file to define users and their key URLs or GitHub usernames.
46-
2. If using the `api` method, either export your GitHub token:
105+
### Command Line Options
106+
107+
```bash
108+
./sync-ssh-keys.sh [OPTIONS]
109+
110+
OPTIONS:
111+
--self-update Update the script to the latest version from GitHub
112+
--help, -h Show help message
113+
--version, -v Show version information
114+
```
115+
116+
### Environment Variables
117+
118+
- `GITHUB_TOKEN`: GitHub personal access token (overrides `CONF_GITHUB_TOKEN`)
119+
120+
### Basic Usage
121+
122+
```bash
123+
# Run synchronization
124+
./sync-ssh-keys.sh
125+
126+
# Update script to latest version
127+
./sync-ssh-keys.sh --self-update
128+
129+
# Show help
130+
./sync-ssh-keys.sh --help
131+
```
132+
133+
## Examples
134+
135+
### Adding New Users
136+
137+
1. **Add a user with GitHub public keys**:
47138
```bash
48-
export GITHUB_TOKEN=your_token_here
139+
# Edit users.conf
140+
["newuser"]="ghuser:github-username"
49141
```
50-
or set `CONF_GITHUB_TOKEN` in `users.conf`.
51-
3. Make sure the script is executable:
142+
143+
2. **Add a user with keys from a private repository**:
52144
```bash
53-
chmod +x sync-ssh-keys.sh
145+
["secureuser"]="api:https://api.github.com/repos/company/ssh-keys/contents/users/secureuser.keys?ref=main"
54146
```
55-
4. Add to root's crontab:
56-
```cron
57-
*/15 * * * * /usr/local/bin/sync-ssh-keys.sh >> /var/log/ssh-key-sync.log 2>&1
147+
148+
3. **Add a user with keys from a public URL**:
149+
```bash
150+
["webuser"]="raw:https://company.com/keys/webuser.authorized_keys"
58151
```
59-
5. To update the script to the latest version, run:
152+
153+
### GitHub Token Setup
154+
155+
For private repositories, you need a GitHub personal access token:
156+
157+
1. Go to GitHub Settings → Developer settings → Personal access tokens
158+
2. Generate a new token with `repo` scope
159+
3. Add it to your configuration:
60160
```bash
61-
./sync-ssh-keys.sh --self-update
161+
CONF_GITHUB_TOKEN="your_token_here"
62162
```
63163

64-
## Implementation Notes
164+
### Multiple Key Sources
65165

66-
- The script sources `users.conf` for configuration.
67-
- Uses a helper function `fetch_key_file` to fetch keys using the appropriate method.
68-
- Includes a retry mechanism for failed fetch operations (3 attempts with a 2-second delay).
69-
- Only updates a user's `authorized_keys` if the remote file has changed.
70-
- Logs all actions with timestamps.
71-
- The `--self-update` option fetches the latest version of the script from the GitHub repository and replaces the current version.
166+
You can configure users with different key sources:
72167

73-
## Examples
168+
```bash
169+
declare -A USER_KEYS=(
170+
["prod-user"]="api:https://api.github.com/repos/company/prod-keys/contents/prod-user.keys?ref=main"
171+
["dev-user"]="ghuser:dev-github-username"
172+
["external-user"]="raw:https://partner.com/keys/external-user.keys"
173+
)
174+
```
74175

75-
### Adding a New User
76-
1. Add the user to `users.conf`:
77-
```bash
78-
["newuser"]="ghuser:newuser-github-username"
176+
## Automation
177+
178+
### Cron Setup
179+
180+
Add to root's crontab for automated synchronization:
181+
182+
```bash
183+
# Edit crontab
184+
sudo crontab -e
185+
186+
# Add entry (sync every 15 minutes)
187+
*/15 * * * * /path/to/sync-ssh-keys.sh >> /var/log/ssh-key-sync.log 2>&1
188+
```
189+
190+
### Systemd Timer
191+
192+
Create a systemd service and timer:
193+
194+
1. **Create service file** `/etc/systemd/system/ssh-key-sync.service`:
195+
```ini
196+
[Unit]
197+
Description=SSH Key Synchronization
198+
Wants=ssh-key-sync.timer
199+
200+
[Service]
201+
Type=oneshot
202+
ExecStart=/path/to/sync-ssh-keys.sh
203+
User=root
204+
205+
[Install]
206+
WantedBy=multi-user.target
207+
```
208+
209+
2. **Create timer file** `/etc/systemd/system/ssh-key-sync.timer`:
210+
```ini
211+
[Unit]
212+
Description=Run SSH Key Sync every 15 minutes
213+
Requires=ssh-key-sync.service
214+
215+
[Timer]
216+
OnCalendar=*:0/15
217+
Persistent=true
218+
219+
[Install]
220+
WantedBy=timers.target
79221
```
80-
2. Run the script to sync keys:
222+
223+
3. **Enable and start**:
81224
```bash
82-
./sync-ssh-keys.sh
225+
sudo systemctl daemon-reload
226+
sudo systemctl enable ssh-key-sync.timer
227+
sudo systemctl start ssh-key-sync.timer
83228
```
229+
230+
### CI/CD Integration
231+
232+
Use in CI/CD pipelines for automated SSH access management:
233+
234+
```yaml
235+
# GitHub Actions example
236+
- name: Sync SSH Keys
237+
run: |
238+
curl -fsSL https://raw.githubusercontent.com/locus313/ssh-key-sync/main/sync-ssh-keys.sh | bash -s
239+
env:
240+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
241+
```
242+
243+
## Troubleshooting
244+
245+
### Common Issues
246+
247+
**Permission denied errors**:
248+
```bash
249+
# Ensure script is executable
250+
chmod +x sync-ssh-keys.sh
251+
252+
# Run with appropriate privileges
253+
sudo ./sync-ssh-keys.sh
254+
```
255+
256+
**GitHub API rate limits**:
257+
- Use authenticated requests with a GitHub token
258+
- Consider reducing sync frequency
259+
260+
**Network timeouts**:
261+
- Script includes automatic retry logic (3 attempts by default)
262+
- Check network connectivity and firewall settings
263+
264+
### Logging
265+
266+
The script provides detailed logging with timestamps:
267+
268+
```
269+
2025-08-29 12:00:00: Starting SSH key synchronization (version 0.1.0)
270+
2025-08-29 12:00:01: Fetching key file for user 'ubuntu' from https://example.com/keys.txt (method: raw)
271+
2025-08-29 12:00:02: Successfully processed user 'ubuntu'
272+
2025-08-29 12:00:02: Synchronization complete. Processed: 1, Failed: 0
273+
```
274+
275+
## Security Considerations
276+
277+
- Store GitHub tokens securely and rotate them regularly
278+
- Use least-privilege access for GitHub tokens (only `repo` scope if needed)
279+
- Monitor logs for failed authentication attempts
280+
- Validate SSH key sources before adding them to configuration
281+
- Consider using private repositories for sensitive key storage
282+
283+
## FAQ
284+
285+
**Q: Can I use this script with GitLab or other Git providers?**
286+
A: Currently, the script supports GitHub's API. For other providers, use the `raw` method with direct URLs to key files.
287+
288+
**Q: What happens if a user doesn't exist on the system?**
289+
A: The script will log a warning and skip that user, continuing with the next user in the configuration.
290+
291+
**Q: How often should I run the synchronization?**
292+
A: This depends on your security requirements. Common intervals are 15 minutes for development environments and 1 hour for production systems.

0 commit comments

Comments
 (0)