server-fist-steps(1)

glfmn.io server-fist-steps(1)
Name

server-fist-steps

Trying to remember what to do first on a new linux server

Introduction

I host some stuff on a server, and I am trying to do a better job of it by using Ansible to maintain things; however, even before I can use Ansible on a new sever, there are a few first steps I need to do…

Unfortunately, I can never remember what they are, so I am documenting them for me and anyone else that happens to find this page.

Creating a user

Through my cloud provider, I created an Ubuntu server with a static IP address and root user.

Log in via ssh using the command:

ssh root@10.10.10.10 # Use the server's static IP

Once logged in, create a new user using the interactive adduser command:

adduser admin # In place of admin, use whatever name you like

This should prompt you to add a password and optional information to your user.

Next we add the user (admin in this case) to the sudo group, so the user has administrative privileges:

usermod -aG sudo admin # replace admin with your user name

Generating an SSH Key

If you do not already have an ssh key, generate one using:

ssh-keygen -C admin # Use any comment that you find useful

It will ask for a file name; it will generate a public key file like this one:

~/.ssh/admin.pub
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILW3/HFZ5jc9LBdfRB/pGtt/+gzL+b/96psasefYcmuP admin

Do not share the private key!

Add SSH key to your server

Now we need to copy the public key to the user we intend to log in as on the server. Luckily, ssh-copy-id can help us with this process. For example:

ssh-copy-id -i .ssh/admin admin@10.10.10.10

According to the manual, ssh-copy-id will attempt to log into the server with each provided key, and if it fails, will log in at the end and add each public key that failed to the user's authorized_keys file.

Keys in the authorized_keys file can bypass password authentication. As long as the private key stays private, this is more secure than password authentication as only people in possession of the key can log in. This means nobody can try to guess the password of your user and use it to log in.

-i identity_file
The path to the SSH key we want to add to the host. By default, generated keys get placed in ~/.ssh, but if you gave a custom file-path when you invoked ssh-keygen, use that path instead.
-n
Don't actually install the keys, just list which keys would be installed. Add this argument if you just want to try out the command without changing anything.
admin@10.10.10.10
Instead of admin, use the name of the user you created earlier, and instead of 10.10.10.10, use the IP of your server.

Log back into the server

Log into the server using your new ssh key like so:

ssh admin@10.10.10.10

You should be able to log in with no password.

SSH Config

Finally, we can make some basic no-brainer SSH config changes.

First, disable password and root login now that our SSH keys are configured:

/etc/ssh/sshd_config
PasswordAuthentication no
PermitRootLogin no

Change the port sshd uses:

/etc/ssh/sshd_config
# use a different port!!!
Port 4761 

Verify the sshd_config works using sshd -t.

And restart the sshd service.

sudo systemctl restart sshd

Sidequest: Secure passwordless sudo

Using a PAM, one can configure the server to use the SSH key authentication agent for sudo permissions instead of a password.

PAM — Pluggable Authentication Modules
Linux system that allows for custom password management, such as using hardware tokens or one-time-passwords for user login.

We can use the pam_ssh_agent_auth module to allow using ssh as the auth module for sudo (or several other systems which use PAM).

However, I gather that setting this up requires compiling code and doing some gnarly config. My server does not have a pam_ssh_agent_auth.so (or similarly named) file. I'd also need to edit some gnarly config files, so best left as a future exercise.

Troubleshooting SSH Host Keys

As some troubleshooting, if the host is missing SSH host keys, ssh-keygen can do this easily like so:

sudo ssh-keygen -A
-A
From the manual page: Generate host keys of all default key types (rsa, ecdsa, and ed25519) if they do not already exist. The host keys are generated with the default key file path, an empty passphrase, default bits for the key type, and default comment. If -f has also been specified, its argument is used as a prefix to the default path for the resulting host key files. This is used by system administration scripts to generate new host keys.

As far as I can tell, this should only be the case if something is going wrong.

If using the Ansible playbook provided in Jeff Geerling's book on Ansible, be sure to add become: yes. This is because the host keys require root permissions to read! Also, run the playbook with -K if passwordless sudo is not set up.

1---
2- hosts: hosts # replace with your host name
3 handlers:
4 - name: restart ssh
5 service: name=ssh state=restarted
6 tasks:
7 - name: Update SSH Configuration
8 become: yes
9 lineinfile:
10 dest: /etc/ssh/sshd_config
11 regexp: "{{ item.regexp }}"
12 line: "{{ item.line }}"
13 state: present
14 validate: 'sshd -t -f %s'
15 with_items:
16 - regexp: "^PasswordAuthentication"
17 line: "PasswordAuthentication no"
18 - regexp: "^PermitRootLogin"
19 line: "PermitRootLogin no"
20 - regexp: "^Port"
21 line: "Port 4761" # use a different port!!!
22 notify: restart ssh

Be sure to update the port to match in your hosts file.