blog

My blog at www.shimmy1996.com

git clone git://git.shimmy1996.com/blog.git

2017-09-25-my-server-setups-and-whatnot.en.md (12989B)

    1 +++
    2 title = "My Server Setups and Whatnot"
    3 draft = false
    4 date = 2017-09-25
    5 slug = "my-server-setups-and-whatnot"
    6 +++
    7 
    8 ## Why move the blog? And to where? {#why-move-the-blog-and-to-where}
    9 
   10 After putting up with the clunky WordPress blog (and Bluehost's 2003-looking admin panel for that matter) for three years, I finally decided to ditch everything I currently have and restart my blog in a more civilized manner. There was a couple of things that I was not happy about my old WordPress setup, namely:
   11 
   12 -   Clunky and eats up my server storage.
   13 -   Not as easy way to back up with tools I know.
   14 -   Does not come with a command line interface, which is becoming my preferred way of doing almost anything.
   15 -   Lacking some basic features I wanted, i.e. multilingual support. As powerful as WordPress may be in the right hands, I do not want to invest too much effort in learning CSS/js/php nor do I want to use some plugin from some sketchy WordPress plugin marketplace.
   16 -   These theme and plugin marketplaces creeps me out in the same way as ubuntu software center.
   17 -   WordPress has a lot of features I do not actually need, i.e. user permission system, which is an overkill for my personal blog site.
   18 
   19 Picking an alternative blogging system was not too hard once I am aware of my needs: a fast and minimalist static site generator implemented in a language I know (or I found valuable to learn) with out-of-the-box multilingual support, a.k.a. `hugo`.
   20 
   21 As for hosting services, I considered github pages and netlify to be fast and easy solutions but I want something more substantial for a personal blog, like a VPS. Besides, github pages not supporting https for custom domains is a deal breaker for me. I filtered down the list of VPS hosting providers with Arch Linux support and I ended up with DigitalOcean. Since I wanted to completely sever my connection with Bluehost, I also moved my domain name host to Google Domains.
   22 
   23 
   24 ## Install Arch Linux {#install-arch-linux}
   25 
   26 Do note that Arch Linux is probably not the best suited server Linux distro. Use a non-rolling distro if stability is a concern. I use it only because I also run it on all my other computers. Backup the droplet often if you decided to go down this route: it hasn't happened to me yet but I've heard people complaining about Arch breaking too often.
   27 
   28 
   29 ### Installation {#installation}
   30 
   31 Apparently my information on DigitalOcean supporting Arch Linux is outdated, as they stopped supporting it a while back. Thankfully, it is still not to hard to bring Arch Linux to a droplet (this is how DigitalOcean refer to a server) due to the awesome project [digitalocean-debian-to-arch](https://github.com/gh2o/digitalocean-debian-to-arch). All I needed to to was [set up a droplet](https://www.digitalocean.com/community/tutorials/how-to-create-your-first-digitalocean-droplet), `ssh` into the server, and follow the instructions:
   32 
   33 ```sh
   34 # wget https://raw.githubusercontent.com/gh2o/digitalocean-debian-to-arch/debian9/install.sh -O install.sh
   35 # bash install.sh
   36 ```
   37 
   38 
   39 ### Low Level Setup {#low-level-setup}
   40 
   41 Once the script finishes running, I have an Arch Linux system running on my droplet with internet access. Most of the additional setups needed can be found in [Arch Wiki](https://wiki.archlinux.org/index.php/Installation%5Fguide). Since I am by no means a great tutorial writer, I suggest referring to Arch Wiki for detailed steps. The recorded commands here are just for book-keeping purposes and is by no means the best way to do things.
   42 
   43 
   44 #### System Clock {#system-clock}
   45 
   46 Sync system clock and set time zone.
   47 
   48 ```sh
   49 # timedatectl set-ntp true
   50 # timedatectl settimezone <Region>/<City>
   51 ```
   52 
   53 
   54 #### Base Packages {#base-packages}
   55 
   56 Install/update base packages.
   57 
   58 ```sh
   59 # pacman -S base base-devel
   60 ```
   61 
   62 
   63 #### Fstab {#fstab}
   64 
   65 Generate `fstab`.
   66 
   67 ```sh
   68 # genfstab -U / >> /etc/fstab
   69 ```
   70 
   71 
   72 #### Set Locale {#set-locale}
   73 
   74 Uncomment `en_US.UTF-8 UTF-8` in `/etc/locale.conf` then generate locale with:
   75 
   76 ```sh
   77 locale-gen
   78 ```
   79 
   80 Set `LANG=en_US.UTF-8` in `/etc/locale.conf`.
   81 
   82 
   83 #### Hostname {#hostname}
   84 
   85 Edit `/etc/hosts` and add hostname of droplet:
   86 
   87 ```sh
   88 127.0.1.1    <hostname>.localdomain <hostname>
   89 ```
   90 
   91 
   92 #### Boot Loader and Initramfs {#boot-loader-and-initramfs}
   93 
   94 Optimizations for intel processors:
   95 
   96 ```sh
   97 # pacman -S intel-ucode
   98 # grub-mkconfig -o /boot/grub/grub.cfg
   99 ```
  100 
  101 Add `crc32` modules to initramfs, as otherwise the droplet fails to boot. Edit `/etc/mkinitcpio.conf` :
  102 
  103 ```sh
  104 MODULES= "crc32 libcrc32c crc32c_generic crc32c-intel crc32-pclmul"
  105 ```
  106 
  107 Regenerate the initramfs image.
  108 
  109 ```sh
  110 # mkinitcpio -p linux
  111 ```
  112 
  113 
  114 #### Root Password {#root-password}
  115 
  116 You know the drill.
  117 
  118 ```sh
  119 # passwd
  120 ```
  121 
  122 
  123 ### User Setups {#user-setups}
  124 
  125 Here are some additional settings to make Arch Linux more useable.
  126 
  127 
  128 #### Creature User {#creature-user}
  129 
  130 Obviously it is not a good idea to use root account:
  131 
  132 ```sh
  133 # useradd -m -G wheel -s /bin/bash <username>
  134 # passwd <username>
  135 ```
  136 
  137 
  138 #### Add User to Sudoer {#add-user-to-sudoer}
  139 
  140 Edit `/etc/sudoers` and add:
  141 
  142 ```sh
  143 <username> ALL=(ALL) ALL
  144 ```
  145 
  146 
  147 #### Login As User {#login-as-user}
  148 
  149 We will finish the rest of the configuration using the user account.
  150 
  151 ```sh
  152 # su <username>
  153 ```
  154 
  155 
  156 #### Package Manager {#package-manager}
  157 
  158 I used to use `packer` as wrapper around AUR and `pacman`. However, after learning about [inherent insecurity](https://wiki.archlinux.org/index.php/AUR%5Fhelpers#Comparison%5Ftable) in their package building processes, I switched to a more secure AUR helper `trizen` (`pacaur` is another choice, and fun fact: there is a reddit bot that tells you to switch to `pacaur` every time `yaourt` is mentioned in a post): `trizen` prompts user to inspect `PKGBUILD`, `*.install` and other scripts before sourcing them and `trizen` is written in Perl instead of Bash. To install `trizen`, first install dependencies via `pacman` according to its [AUR Page](https://aur.archlinux.org/packages/trizen/), then clone its [git repo](https://github.com/trizen/trizen) to a local directory. Navigate to the directory containing `PKGBUILD` and run
  159 
  160 ```sh
  161 $ makepkg
  162 ```
  163 
  164 to make package and
  165 
  166 ```sh
  167 $ pacman -U trizen-*.pkg.tzr.xz
  168 ```
  169 
  170 to install `trizen`.
  171 
  172 
  173 #### Useful Packages {#useful-packages}
  174 
  175 Once package manager is in place, install packages to your heart's content! Some of my bread-and-butter packages include `emacs` (I installed the cli-only version, `emacs-nox`), `tmux` (terminal multiplexor, very useful), `zsh`, `vim` (for quick edits), and etc.
  176 
  177 
  178 ## Security Related Stuff {#security-related-stuff}
  179 
  180 Now that a usable Arch Linux installation is in place, I would employ some security measures before hosting my website on it.
  181 
  182 
  183 ### Secure Login via `ssh` {#secure-login-via-ssh}
  184 
  185 On local machine, generate your ssh keypair:
  186 
  187 ```sh
  188 $ ssh-keygen -t rsa
  189 ```
  190 
  191 Send your ssh keys to server:
  192 
  193 ```sh
  194 $ ssh-copy-id <username>@<server>
  195 ```
  196 
  197 Now, on server, make the following edits to `/etc/ssh/sshd_config` :
  198 
  199 ```sh
  200 PermitRootLogin no
  201 ChallengeResponseAuthentication no
  202 PasswordAuthentication no
  203 UsePAM no
  204 AllowUsers <username>
  205 ```
  206 
  207 These changes will disable root login, disable password login and only allow specified user to login via ssh.
  208 
  209 It is advisible to also change the default port (22) used for ssh connection, in the same file, specify port by (please remember this port selection):
  210 
  211 ```sh
  212 port <non-std-port>
  213 ```
  214 
  215 For these changes to take effect, restart `ssh` daemon:
  216 
  217 ```sh
  218 $ sudo systemctl restart sshd.service
  219 ```
  220 
  221 Keep this `ssh` session intact and attempt to start another `ssh` connection in local machine to see if the changes have taken effect (the original session is needed in case things are not working):
  222 
  223 ```sh
  224 $ ssh -p <non-std-port> <username>@<server>
  225 ```
  226 
  227 
  228 ### Firewall Settings {#firewall-settings}
  229 
  230 I use `ufw` as my firewall and it is very easy to setup. Install `ufw` with `trizen` and enable the desired ports:
  231 
  232 ```sh
  233 $ trizen -S ufw
  234 $ sudo ufw allow <port>/<protocol>
  235 ```
  236 
  237 For instance, to allow `ssh` communication, allow `22/tcp` or `ssh` (if you used a non-standard port, allow `<non-std-port>/tcp`). Some other useful ports are:
  238 
  239 | Port      | Usage                               |
  240 |-----------|-------------------------------------|
  241 | `80/tcp`  | `http`                              |
  242 | `443/tcp` | `https`                             |
  243 | `143`     | imap access                         |
  244 | `993`     | imap over `ssl`                     |
  245 | `25`      | receive incoming mail               |
  246 | `587`     | smtp access (with or without `ssl`) |
  247 
  248 To review the added ports and enable them:
  249 
  250 ```sh
  251 $ sudo ufw show added
  252 $ sudo ufw enable
  253 ```
  254 
  255 Auto start up:
  256 
  257 ```sh
  258 $ sudo systemctl enable ufw.service
  259 ```
  260 
  261 
  262 ### Sync Server Time {#sync-server-time}
  263 
  264 Sync server time with `ntp` :
  265 
  266 ```sh
  267 $ trizen -S ntp
  268 $ sudo systemctl enable ntpd.service
  269 ```
  270 
  271 Check time server status with:
  272 
  273 ```sh
  274 $ ntpq -p
  275 ```
  276 
  277 
  278 ### Setting up PTR Record {#setting-up-ptr-record}
  279 
  280 It turns out that DigitalOcean handles this automatically, all I needed to do is set the droplet name to a Fully Qualified Domain Name (FQDN), in this case `shimmy1996.com`. I then checked if the record is in place with:
  281 
  282 ```sh
  283 $ dig -x <ip_address>
  284 ```
  285 
  286 
  287 ## Firing up the Server {#firing-up-the-server}
  288 
  289 Next step would be actually preparing the server for serving contents.
  290 
  291 
  292 ### Create Web Directory {#create-web-directory}
  293 
  294 Create a directory for serving web contents, a common choice would be:
  295 
  296 ```sh
  297 $ mkdir ~/public_html
  298 ```
  299 
  300 Make sure to give this directory (including the user `home` folder) appropriate permission with `chmod` (`755` would normally work). Populate the directory with a simple `index.html` for testing if you want.
  301 
  302 
  303 ### Instal `nginx` {#instal-nginx}
  304 
  305 Install `nginx` with `trizen`, and edit `/etc/nginx/nginx.conf` to set up `http` server (the one set to `listen 80 default_server`):
  306 
  307 ```sh
  308 server_name www.<domainname> <domainname>
  309 root /path/to/public_html
  310 ```
  311 
  312 For the `server_name` line add as many as you want. You may want to put your mail server address on it as well so that you can generate a single ssl certificate for everything. After these changes are made, (re)start and enable `nginx`:
  313 
  314 ```sh
  315 $ sudo systemctl restart nginx.service
  316 $ sudo systemctl enable nginx.service
  317 ```
  318 
  319 
  320 ### DNS Setup {#dns-setup}
  321 
  322 The next step is to set up DNS records for our server. There are three types of records that need to be set up initially, `NS`, `A`, and `CNAME`. I also included some other useful records:
  323 
  324 | Type    | Hostname              | Value                         | Usage                                                    |
  325 |---------|-----------------------|-------------------------------|----------------------------------------------------------|
  326 | `NS`    | @                     | nameserver address            | specifiec name server to use                             |
  327 | `A`     | @                     | supplied IPv4 address         | redirects host name to IPv4 address                      |
  328 | `CNAME` | www (can be anything) | @                             | sets `www.<hostname>` as an alias                        |
  329 | `MX`    | @                     | mail server address           | specifiec mail server to use                             |
  330 | `CAA`   | @                     | authorizor of SSL certificate | prevents other authority from certifying SSL certificate |
  331 
  332 In my case, though I use Google Domains to host my domain, I still use DigitalOcean's name server. So I needed to setup these records on DigitalOcean and `NS` records on Google Domains.
  333 
  334 After this step, you website should be accessible via your domain name, although it may take a few hours for the DNS record to populate.
  335 
  336 
  337 ### SSL Certificate {#ssl-certificate}
  338 
  339 [Let's Encrypt](https://letsencrypt.org) is a great project and [`certbot`](https://certbot.eff.org/) is an awesome tool for SSL certificate generation. Kudos to the nice folks at EFF and Linux Foundation. I simply followed the instructions on [EFF site](https://certbot.eff.org/#arch-nginx):
  340 
  341 ```sh
  342 $ sudo pacman -S certbot-nginx
  343 $ sudo certbot --nginx
  344 ```
  345 
  346 To provide some extra credibility to the certificate, I added an `CAA` record in my DNS settings with issue authority granted for `letsencrypt.org`. For now Let's Encrypt does not support wildcard certificate but will be [January 2018](https://letsencrypt.org/2017/07/06/wildcard-certificates-coming-jan-2018.html), and this is why I added a bunch of subdomains into my `nginx.config` (so that the certificate covers these subdomains as well).
  347 
  348 
  349 ## What Now? {#what-now}
  350 
  351 After a couple hours (mostly waiting for DNS records to populate), and my website is online again. With a VPS at my disposal, I also host my personal email now and I might organize my random notes pieced from various websites into a post as well. I am still trying to figure out an efficient workflow for writing multilingual post with `org-mode` in `hugo` and once I am convinced I have found an acceptable solution, I will also post it.