Configuring DNS and SSH, pulling in your config repository
Now that your server is up, running and reachable by its IP address, let's add some DNS records, ensure SSH is working, and bring in our config repository.
Cloudflare DNS
In this course we're using Cloudflare for DNS hosting and content delivery, so let's go to our Cloudflare Dashboard and add three new DNS records to point to our newly provisioned server.
The domain I'm using for this course is uncached.org
which currently has no
DNS records. The new records I'm going to add are:
A
record fororigin.uncached.org
pointing to138.197.11.227
(DNS only)CNAME
record for@
(root/apex) pointing toorigin.uncached.org
(proxied)CNAME
record forwww
pointing touncached.org
(proxied)
Here's a screenshot of my Cloudflare dashboard. Note that your domain and IP address will be different.
The first record points directly to my provisioned server (hence DNS only). This address is used to access services directly on the VM or dedicated server, such as SSH and external MySQL when needed.
However, we'd like our web traffic to go through Cloudflare's CDN service for
performance and security reasons. This is why my second record points to the
same server (by pointing at the first record) but with a proxied status,
meaning it will resolve to Cloudflare's proxy servers. My third record extends
the chain to the www
subdomain.
We can now verify these records using dig
in the Terminal:
dig origin.uncached.org
dig uncached.org
dig www.uncached.org
The first one resolves to the server I recently created. The next two resolve to
Cloudflare's edge IP addresses. Note that even though we provided CNAME
records,
Cloudflare flattens these down to A
records in its response.
SSH access
DNS changes usually take some time to propagate globally. New records should appear almost instantly, but if you're updating existing records, it may take some more time, depending on the TTL value of the previous record (Cloudflare defaults this to 5 minutes).
After the DNS changes have propagated, using this new A
record, I should
be able to access the SSH service on my server:
ssh [email protected]
Note that depending on the OS and version you've provisioned, you might not be
able to directly log in as root
, and may be forced to log in as another user
(such as admin
or ubuntu
). We'll configure a proper non-root user in the
next module, but you may need to sudo su
to turn into root for now.
The first thing I like to do on a newly provisioned server is change the hostname, usually to the FQDN (fully qualified domain name) of the server:
hostnamectl set-hostname origin.uncached.org
This is not strictly necessary, but helps keep things organized. Having a
resolvable name may also help some applications that expect one. I personally
also use the hostname
command as a sanity check, before running a potentially
disruptive command, like a reboot.
Config repository
Now would also be a good time to pull in our configuration repository from the previous module. Don't worry if it's quite empty at this stage, we'll start using it very soon.
I personally like to use GitHub to centralize my config repositories. This allows me to update things when I'm travelling, grant access to coworkers, use issues and pull requests, and even automate things.
You can, however, host your repository elsewhere, as long as it's accessible by the server, and as long as it's not on the server itself.
Let's create a new empty repository on GitHub for our server configuration files:
Make sure it's private since it will contain potentially sensitive files. If you've followed the earlier module you should already have the repository layout committed locally. We can now push that to GitHub:
cd /path/to/config
git remote add origin [email protected]:koddrio/config.git
git push -u origin main
Now that it's on GitHub, we'll need to pull it down to our new server. However, our server will not have access to the Git repository because it's private, so you'll see an error when you attempt to do so:
ssh [email protected]
git clone [email protected]:koddrio/config.git
[email protected]: Permission denied (publickey).
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
There are multiple ways to allow the server to access the repository. The easiest, and my personal favorite, is SSH agent forwarding.
SSH agent forwarding
This technique allows you to forward your local SSH agent (the gatekeeper of your SSH keys) and use that agent on a remote server. The remote server will be able to securely use your keys while you're connected via SSH.
You can manually start an SSH session with agent forwarding, using the -A
flag
like this:
ssh -A [email protected]
Alternatively, you can update your local SSH configuration (usually in ~/.ssh/config
)
to automatically forward the agent to certain hosts, for example:
Host origin.uncached.org
ForwardAgent yes
This way the agent will be forwarded every time you connect. Never forward your SSH agent to a host you don't trust. While the agent will not leak your SSH private keys, it will allow the remote host to use those keys while you are connected.
The GitHub Docs site has a great article on SSH agent forwarding if you'd like to learn more. If you're looking for an alternative way to grant your server access to your GitHub repository, deploy keys may be a good fit.
We should now be able to pull our config repository on our remote host:
ssh -A [email protected]
mkdir /config
cd /config
git clone [email protected]:koddrio/config.git .
Cloning into 'config'...
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 5 (delta 0), reused 5 (delta 0), pack-reused 0 (from 0)
Receiving objects: 100% (5/5), done.
Your (future) configuration files are now in /config
. While on this
server via SSH we can pull any changes from the repo, but also push back to the
repository when we make changes locally.
I like to keep my config repository in /config
but you can use another
location if you like (/srv/config
, /opt/config
, etc.) but note that it has
to be world-readable for different services to access their configuration files.