Files
hermes-skills/skills/devops/infrastructure-automation/references/routeros-ssh-key-deployment.md
T

4.5 KiB

RouterOS SSH Key Deployment (v7.18+)

Deploying SSH public keys to RouterOS v7 via CLI over SSH is surprisingly finicky. This doc catalogs what works and what doesn't.

What DOES work

Method A — /file/add name="" contents="" (v7 clean, no FTP needed)

This is the most reliable method discovered. Works on RouterOS 7.18.2 (CCR2004):

# Create file with the public key content
/file/add name="wisp-key.txt" contents="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... wisp-backup"

# Import the key for a user
/user ssh-keys import public-key-file="wisp-key.txt" user=shonuff

# Clean up the source file
/file/remove [find name="wisp-key.txt"]

Limitations: The contents= value is part of the SSH command string. RouterOS SSH session seems to have a ~170 character line limit. The Ed25519 key line is ~92 chars — fits fine. An RSA 4096 key line (~500+ chars) would NOT fit.

Escaping: The key content does NOT contain $, \, or " in the base64-encoded section, so double quotes around contents= work without escaping. If you ever deploy a key that does contain these, use hex encoding (Method C below).

Method B — /user ssh-keys/add user= key= (native, no file at all)

RouterOS v7 supports creating the SSH key directly without a file intermediary. This is the cleanest approach:

/user ssh-keys/add user=shonuff key="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... wisp-backup"

Same line-length limitation as Method A (~170 chars over SSH). For keys that exceed this, use Method A (/file/add contents=) which is verified compatible.

Note: This method is verified working on RouterOS 7.18.2. The user ssh-keys print command requires the full group to read (or a user with policy privileges) — write group gets "Permission denied" when listing but the key import itself succeeds and SSH key auth works. Test via ssh -i key user@host /system identity print.

Method C — Hex-encoded script (for long keys)

Method C — Hex-encoded script (for long keys)

For RSA keys longer than the SSH line limit, write the key as a RouterOS script using hex escapes:

/system script add name=deploy-key source=":local key \"\\73\\73\\68...\"; :put \$key file=wisp-key.txt"
/system script run deploy-key
/user ssh-keys import public-key-file=wisp-key.txt user=wisp-backup

Generate the hex escape string from Python:

key = "ssh-ed25519 ..."
hex_escaped = ''.join(f'\\{b:02X}' for b in key.encode())

What does NOT work

:put ... file= — Syntax error on RouterOS 7.18

:put "abc123" file=test.txt  # expected end of command

The file= parameter does not exist on :put in RouterOS 7.18. This is a frequently-seen outdated suggestion in forum posts. It was removed or never existed in 7.x.

:put ... file="test.txt" — Same error, with or without quotes.

:convert from=base64 with long strings truncated by SSH line limit

The :convert from=base64 command itself works (verified with short test), but the base64 string + command prefix exceeds RouterOS's SSH line length limit (~170 chars).

SCP/SFTP — "exec request failed on channel 0"

MikroTik RouterOS does not support the SCP or SFTP subsystems over SSH (verified on 7.18.2). Even with scp -O legacy protocol flag, the router rejects the channel request.

FTP — disabled by default

FTP service is installed but disabled (/ip service print shows X flag). You can temporarily enable it, but the write user group has !ftp policy by default. The full group does have FTP. Enabling FTP+changing user group is possible but a hassle vs Method A.

Key verification

After importing, verify key-based auth works:

ssh -i ~/.ssh/wisp_rsa user@192.168.88.1 /system identity print

Once an SSH key is assigned to a RouterOS user, password-based SSH login is automatically disabled for that user (RouterOS v7 behavior, not a bug).

Permission notes

  • write group: Can use SSH keys (key auth works), but trying /user ssh-keys print returns "Permission denied". Import still succeeds (exit 0). Test via ssh -i key user@host /system resource print instead.
  • full group: Can list and manage SSH keys. If you need to verify keys from SSH, use full or read group with correct policy.
  • The !ftp policy in write group blocks both FTP and /tool/fetch — anything that tries the FTP subsystem. Not a bug, documented behavior.

Cleanup

Remove the intermediate .txt key file after successful import:

/file/remove [find name="wisp-key.txt"]