Deploying my blog with rsync and ssh
A couple of days ago I decided to deploy a CI/CD system at one of the servers I manage in order to automate certain processes, like generating and deploying my blog, building Husky and other apps, and more in the future.
One of the many things I need is to deploy the blog using rsync and ssh, so the content is transferred securely and without my intervention. The problem I found was that putting the ssh key password at the pipeline was almost an impossible task, because it was not designed that way, so I had to go with a passwordless ssh key.
I will not get into the details of the pipeline setup, because you can generate your static blog with a lot of generators and you can choose the tool you need to deploy it as you see fit. In this case, it is hugo.
Passwordless SSH key
In order to generate a passwordless ssh key, just execute the command
ssh-keygen:
$ ssh-keygen -t ed25519 -a 100 -C "<COMMENT>"
The -a argument is used to specify the number of rounds of key derivation
functions to use when generating the key. I put 100, you can put whatever number
you want. You can change ed25519 to rsa if you want another key type.
<COMMENT> may be whatever you want. In my case, I just put deploy.
After putting the path where the ssh key is stored, and press Enter when you are asked to put a password, you will have a passwordless ssh key generated.
Rsync setup
Now that the ssh key is generated, it is the moment to setup the server. If you do not have created the directory and file is needed, then execute these commands:
$ mkdir .ssh && cd .ssh
$ touch authorized_keys
$ chmod 0600 authorized_keys
After this, edit the file authorized_keys with the editor of your choice, and
put the following line (read before copy and paste):
restrict,command="rsync --server <RSYNC_ARGS> --delete . <PATH>",no-agent-forwarding,no-port-forwarding,no-pty,no-user-rc,no-X11-forwarding <SSH_KEY_PUB_CONTENT>
This means:
restrict: This option is designed to set restrictions on an SSH key.--server: In this mode, rsync waits for a connection from a remote system running rsync in client mode. In only applies on the server side.<RSYNC_ARGS>: The arguments of your rsync command executing at the pipeline. They must be the exact same ones. In my case, those are-PavhzC.<PATH>: The absolute path where your blog is going to be deployed.<SSH_KEY_PUB_CONTENT>: the content of the .pub file of the passwordless ssh key you generated before.no-agent-forwarding: This option disables SSH agent forwarding, which allows the user to use their SSH agent to authenticate to remote servers. Disabling agent forwarding can help improve security by preventing the user’s SSH agent from being used to authenticate to other servers.no-port-forwarding: This option disables port forwarding, which allows the user to forward network connections from their local machine to the remote server. Disabling port forwarding can help improve security by preventing the user from inadvertently exposing services on their local machine to the internet.no-pty: This option disables the allocation of a pseudo terminal (pty) for the session. Disabling pty allocation can help improve security by preventing the user from running interactive commands on the remote server.no-user-rc: This option disables the execution of the user’s shell initialization files on the remote server, which typically execute commands when the user logs in interactively (e.g., running malicious scripts).no-X11-forwarding: This option disables X11 forwarding, which allows the user to run graphical applications on the remote server and display them on their local machine. Disabling X11 forwarding can help improve security by preventing the user from inadvertently exposing their local X11 server to the internet.
It should look like this (the ssh key in this example has been randomly generated, use yours):
restrict,command="rsync --server -PavhzC --delete . /var/www/blog",no-agent-forwarding,no-port-forwarding,no-pty,no-user-rc,no-X11-forwarding ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIN22zZv3/Yz+d+/Y/z+Kjqo5XjJK5X5c5+T1Gj6/Z6WQ deploy
Once the server-side is setup, you can now deploy your blog from a pipeline using rsync and ssh with a command like this:
$ rsync -e "ssh -i <SSH_PRIVATE_KEY_PATH>" <RSYNC_ARGS> --delete ./public/ <HOST>:<PATH>
<SSH_PRIVATE_KEY_PATH>: The absolute path of the private ssh key used for the deployment.<RSYNC_ARGS>: The same arguments as specified in the command authorized at the server. DO NOT USE THE--serverargument here!<HOST>: The server where the content is going to be deployed. It can beuser@hostor just the host if you have your own ssh config.
You may need to specify a port in case the default one is not being used, in
which case, add -p <SSH_PORT> to the -e argument, like this:
$ rsync -e "ssh -i <SSH_PRIVATE_KEY_PATH> -p <SSH_PORT>" -<RSYNC_ARGS> --delete ./public/ <USER>@<HOST>:<PATH>
If the deployment fails and rsync cuts the connection, review the rsync args and the path, you might not have the same put in both commands.
Pipeline setup
With all of this, you can now setup the pipeline of your preference to automate the deployment of your blog (or any files).
Conclusion
This is an approach to allow a command being run with a specific ssh key, and allows the user to use passwordless ssh keys for deployments.