4.2 KiB
SSH Keys Setup Guide
Security Notice
SSH private keys (.ppk, .pem, id_rsa, etc.) should NEVER be:
- Stored in the application directory
- Committed to git repositories
- Placed in web-accessible locations
Recommended Setup
1. Create Secure Keys Directory on Server
# On your production server
sudo mkdir -p /var/crew-keys
sudo chmod 700 /var/crew-keys
2. Place Your SSH Key
# Copy your key to the secure location
sudo cp /path/to/your/root.ppk /var/crew-keys/
sudo chmod 600 /var/crew-keys/root.ppk
sudo chown root:root /var/crew-keys/root.ppk
3. Verify Permissions
ls -la /var/crew-keys/
# Should show: drwx------ (700) for directory
# Should show: -rw------- (600) for key file
Docker Configuration
The docker-compose.prod.yml and docker-compose.dev.yml files are configured to mount /var/crew-keys as a read-only volume:
volumes:
- /var/crew-keys:/var/keys:ro
The :ro flag ensures the container can only read the keys, not modify them.
Application Configuration
The config/filesystems.php references the key at:
'privateKey' => '/var/keys/root.ppk',
This path is inside the container and maps to /var/crew-keys/root.ppk on the host.
Testing
To verify the SFTP connection works:
docker exec crewsportswear_app_prod php -r "
use League\Flysystem\Sftp\SftpAdapter;
try {
\$adapter = new SftpAdapter([
'host' => '35.232.234.8',
'port' => 22,
'username' => 'root',
'privateKey' => '/var/keys/root.ppk',
'root' => '/var/www/html/images',
'timeout' => 10,
]);
echo 'SFTP connection: SUCCESS';
} catch (Exception \$e) {
echo 'SFTP connection failed: ' . \$e->getMessage();
}
"
Troubleshooting
Permission Denied
If you get permission errors:
# Fix directory permissions
sudo chmod 700 /var/crew-keys
# Fix key file permissions
sudo chmod 600 /var/crew-keys/root.ppk
Key Format Issues
PuTTY keys (.ppk) may need conversion for Linux/PHP:
# Convert .ppk to OpenSSH format
puttygen root.ppk -O private-openssh -o /var/crew-keys/root.pem
chmod 600 /var/crew-keys/root.pem
Then update filesystems.php:
'privateKey' => '/var/keys/root.pem',
Local Development — Remote DB via SSH Tunnel
Use the ssh-db profile to connect the local app to a remote database through an SSH tunnel, authenticated with a private key.
1. Configure .env.local
# SSH jump host
SSH_HOST=your.server.ip.or.hostname
SSH_PORT=22
SSH_USER=root
SSH_KEY_PATH=~/.ssh/id_rsa # path to your private key on the Mac host
# DB endpoint as seen from the SSH server
SSH_DB_REMOTE_HOST=127.0.0.1
SSH_DB_REMOTE_PORT=3306
# Tell the app to route through the tunnel container
DB_HOST=db-tunnel
DB_PORT=3306
DB_DATABASE=your_remote_db_name
DB_USERNAME=your_remote_db_user
DB_PASSWORD=your_remote_db_password
2. Start the stack with the tunnel profile
docker compose -f docker-compose.local.yml --profile ssh-db up --build
This starts a db-tunnel sidecar container (Alpine + openssh-client) that creates:
Mac host → [SSH tunnel] → SSH_HOST → DB (SSH_DB_REMOTE_HOST:SSH_DB_REMOTE_PORT)
The app container connects to db-tunnel:3306, which forwards all traffic through the encrypted tunnel.
3. Key requirements
| Requirement | Detail |
|---|---|
| Key format | OpenSSH (id_rsa, id_ed25519) — not .ppk |
| Key permissions | chmod 600 ~/.ssh/id_rsa |
| SSH server | Authorised key must be in ~/.ssh/authorized_keys on SSH_HOST |
Tip: If your key is in PuTTY (
.ppk) format, convert it first:puttygen root.ppk -O private-openssh -o ~/.ssh/id_rsa chmod 600 ~/.ssh/id_rsa
Security Best Practices
✅ DO:
- Store keys outside application directory
- Use restrictive permissions (600 for files, 700 for directories)
- Mount as read-only in Docker
- Keep keys out of version control
- Use SSH key authentication instead of passwords
- Rotate keys regularly
❌ DON'T:
- Commit keys to git
- Store in web-accessible directories
- Use world-readable permissions
- Share keys across multiple services
- Use password-protected keys without proper passphrase management