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.