I'm slowly discovering that I love systems stuff. I've always used Ubuntu as the flavor of Linux on my servers, but I was curious about the differences between Ubuntu and CentOS, so I looked up a few guides and tutorials and spun up a new Digital Ocean droplet with a fresh install of CentOS. I wanted to share what I learned, and all of the things to think about when first getting things set up. I'm also writing this for when future me forgets a step and can't remember the commands.
I'm going to assume that you have working knowledge of the command line for now: changing directories, editing files, and setting file permissions. I'll try to explain anything more exotic than that. If you're not quite there, but you still want to learn, please get in touch, and I'd be happy to walk you through it (and/or write another post for that). This is also a guide for CentOS because that's what I was doing. For that reason, all of the commands are Centos (and probably RHEL) specific. The process and theory should be much the same for other flavors of Linux, though.
I'm not sure how other providers do it, but once you create a droplet on Digital Ocean and your new server is all turned on, they send you an email with the
root password. You'll be able to
ssh into your server using these credentials. If you're on a Mac, you already have
ssh installed and accessible via your terminal app of choice. If you're on Windows, you should look into an
ssh client. I use PuTTY when I need to. Your hosting provider will provide you with an IP address as well.
From now on, if you see something in angle brackets like that, just assume that I mean, "Fill in the placeholder in angle brackets with your own preferred value." It will ask you for your password. Paste it in and hit Enter, and you should be ready to rock!
Right now you're logged in as
root. This is great! It is also bad. When you are logged in as root, typos and little mistakes can cause big problems. It's generally better to sign in and go about your life in a less privileged account, only invoking
sudo to do privilege-y things when you need to. That way, if you accidently try to delete yourself out of existence, you'll have to work a little harder before you succeed. So, we'll need to create this everyday user.
adduser <username> && passwd <username>
This will ask you for a new password for your new user. Make it a good one.
Next, let's make sure that your new user can actually
usermod -aG wheel <username>
We're adding our new user to the
wheel group, which (as long as you're on CentOS 7 or better) means that we'll be able to
sudo without trouble.
Lastly, sometimes there's a default user created:
centos. I don't think we need this user for anything. Remove it with:
Next, we're going to strengthen security by setting up private/public key authentication. A side benefit of this is that you won't need to remember a password if you don't want to anymore. Temporarily switch users so that you're operating as your new user.
In order to authenticate with keys, you'll need a spot to put your public key. Let's create the
We also don't want anyone but us to be able to fiddle around in this directory.
sudo chmod 700 ~/.ssh/
Great! Let's transfer a key. Exit
ssh or open up a new terminal on your local machine. If you don't yet have a private/public key pair, generate one now.
ssh-keygen # Generating public/private rsa key pair. # Enter file in which to save the key (/Users/localuser/.ssh/id_rsa):
Just hit Enter to accept the default file location for your keys. This will create two files.
id_rsa is your private key. This is Very Secret™. Never share this with anyone unless you trust them with your life. Or, at least, your servers. I'd go so far as to say don't put this out on a cloud service or flash drive where it might get hacked, stolen, lost, or blown up.
id_rsa.pub is your public key, and this is the one you can share with people to prove you are who you say you are. This is the file that we want to share with our new server's new user. There are a couple ways to do this:
# Via ssh-copy-id ssh-copy-id <username>@<server-ip> # Via scp scp ~/.ssh/id_rsa.pub <username>@<server-ip>:~/.ssh/authorized_keys # Manually via good ole' fashioned copy/paste cat ~/.ssh/id_rsa.pub # You'll see something like: # ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAmLmwkzQDjEOW1Rj3TP5NldVDqUODVH9xuYrkeaSkxtdP # Copy the whole thing. Then ssh back into your server like normal and create a new file at ~/.ssh/authorized_keys and paste in in. nano ~/.ssh/authorized_keys # Or use emacs or vim or whatever editor you like best. Whatever. Shut up.
Now, the next time you log in as your user, it shouldn't ask you for a password.
And once again, make sure the permissions are as restrictive as possible for this file.
# Once again logged into your server sudo chmod 600 ~/.ssh/authorized_keys
"But wait, shouldn't we do a public key for our
root user as well, so we don't have to type that password either?" you ask. The answer is no. Actually, the most secure way is if your
root user can't even log in from the outside at all! We're now going to edit the configuration for our
ssh daemon (or,
sshd for short) that controls how our server accepts
ssh connections. Most configuration lives in the
/etc directory, and this is no exception.
sudo nano /etc/ssh/sshd_config
Look for the line that says:
You'll want to uncomment it and set that to "no."
Side note: I always think it's funny to add an additional line.
# PermitKennyLogin DANGER ZONE!
My wife, a teacher and not an avid sshd configurer, disagrees.
As extra steps, also change the following lines:
PasswordAuthentication no # If you connect via IPv4: AddressFamily inet # If you connect via IPv6: AddressFamily inet6
The first line turns off all password logins. Without this, your user account is still open to password login, which somebody can do even without your private key. The other lines shrink the amount of shenanigans you have to deal with by refusing to serve people who aren't connecting like you. If you're not going to ever connect via IPv6, why leave that open for some botnet to sniff around?
Lastly, once we've reconfigured a service, we need to reload it.
sudo systemctl reload sshd
And we should be good to go!
We're pretty much done with the security stuff. By now, you should be pretty much secure and feeling safe. Now we're going to focus on turning this server into a pleasant place to work.
yum update && sudo yum upgrade
Watch as your server brings itself up to current.
If you get interrupted or, hypothetically, your dog jumps into your lap while this is happening and just manages to mash the correct keys to abort the upgrade without cleaning up, and you start seeing errors like "yum lock" or "sqlite3 database lock", don't panic.
Check to see if there's still a
yum process active.
ps aux | grep yum
If you see one that shouldn't be active, try to kill it (take note of the process ID (PID) in the second column of the output from the above command).
kill <pid> # Or, if you're feeling feisty and it's not working: kill -9 <pid>
Willy is sorry he caused 90 minutes of frantically Googling error messages.
Now is a good time to install any packages you couldn't be without: Zsh, oh-my-zsh, Ruby, Vim, and git are the first ones that come to mind. I'm going to show you just the first one, because there is one hiccup you might encounter. If you prefer Fish or some other shell, it should most likely be similar.
The first part should make sense.
sudo yum install zsh
Check to see where your executable lives.
where zsh # /usr/bin/zsh
The important thing here is to make sure that this location is in your
/etc/shells file, which is a list of the approved shells.
sudo nano /etc/shells
# List of acceptable shells for chpass(1). # Ftpd will not allow users to connect who are not using # one of these shells. /bin/bash /bin/csh /bin/ksh /bin/sh /bin/tcsh /bin/zsh /usr/local/bin/pwsh /usr/bin/zsh # << Here's the one we're adding.
Once the zsh executable is approved, you can set your own default shell to zsh.
chsh -s $(where zsh)
If you're like me, you're probably reasonably proud of your slowly growing collection of "dot files." But how do you get them from your computer onto the server, quickly, sanely, and repeatably? With Git. I found this article by Nicola Paolucci that I think is brilliant. We're going to use a modified bare Git repository in our local home directory!
On your local machine:
git init --bare $HOME/.dotfiles alias dot='/usr/bin/git --git-dir=$HOME/.dotfiles --work-tree=$HOME' dot config --local status.showUntrackedFiles no echo alias dot='/usr/bin/git --git-dir=$HOME/.dotfiles --work-tree=$HOME' >> ~/.bashrc
We create a bare repo in our home directory to track our dot files, we create the
dot command (or whatever you want to call it) which will function just like the
git command, but just for our dotfiles. We configure it to only show us if our tracked files change, and then we save the
dot command for later.
Now, all we have to do is start tracking some dot files!
dot status dot add .zshrc dot commit -m "Add zshrc" dot remote add origin https://github.com/<you>/dotfiles.git dot push -u origin master
You get all the benefits of Git! You can branch, edit, roll back, diff changes, and more.
On the server, add your same
dot command to your
echo alias dot='/usr/bin/git --git-dir=$HOME/.dotfiles --work-tree=$HOME' >> ~/.zshrc . ~/.zshrc
If there are any stock files that might conflict with the dotfiles you're about to pull in, either delete them or (better), copy them to a backup directory.
mkdir .dotfile-backup mv .bashrc .dotfile-backup mv .zshrc .dotfile-backup
Now we're ready:
git clone --bare <dotfile repo url> $HOME/.dotfiles echo ".dotfiles/" >> .gitignore dot checkout # Just in case: dot config status.showUntrackedFiles no
And now your server should be on its way to being comfy, cozy, and functional!
I don't know about you, but I believe that 98% of the reasons why I learned how to program were to make computers print out funny messages. To that end, I set up my Message of the Day accordingly.
sudo vim /etc/motd
================================== You are a gentleman and a scholar. ==================================
If you can't think of any one-liner affirmations to put in your MOTD, check out this list of compliments I curated for a twitter bot to pepper my brother with.
Now, whenever you log in, your server will greet you with an uplifting message! 😁
I know there's a lot more for me to learn in the system administration realm. I'm starting to stock up on books to read and videos to watch. Did I miss anything important? Do you have any extra protips? Any great resources for learning? Let me know about them! Thanks for reading!
Originally posted on