cmc/cleberg.net

My personal web garden & blog.

clone: git clone https://gitbay.org/cmc/cleberg.net.git

main: content/blog/2022-10-22-alpine-linux.org · raw

  1#+date:        [2022-10-22 Sat 00:00:00]
  2#+title:       Alpine Linux: Minimal Install, Minimal Attack Surface
  3#+description: Installing Alpine Linux as a lightweight, secure server OS.
  4#+slug:        alpine-linux
  5#+filetags:    :linux:
  6
  7* Alpine Linux
  8
  9[[https://alpinelinux.org][Alpine Linux]] is a very small distribution, built on musl libc and busybox. It
 10uses ash as the default shell, OpenRC as the init system, and apk as the package
 11manager. According to their website, an Alpine container "requires no more than
 128 megabytes (MB) and a minimal installation to disk requires around 130 MB of
 13storage." An actual bare metal machine is recommended to have 100 MB of RAM and
 140-700 MB of storage space.
 15
 16Historically, I've used Ubuntu's minimal installation image as my server OS for
 17the last five years. Ubuntu worked well and helped as my original server
 18contained an nVidia GPU (graphics processing unit) and no onboard graphics, so
 19quite a few distributions won't boot or install without a lot of tinkering.
 20
 21Alpine has given me a huge increase in performance across my Docker apps and
 22Nginx websites. CPU (central processing unit) load for the new server I'm using
 23to test Alpine hovers around 0-5% on average with an Intel(R) Core(TM) i3-6100
 24CPU @ 3.70 Gigahertz (GHz).
 25
 26The only services I haven't moved over to Alpine are Plex Media Server and
 27Syncthing, which may increase CPU load quite a bit depending on how many streams
 28are running.
 29
 30** Installation
 31
 32In terms of installation, Alpine has an incredibly useful [[https://wiki.alpinelinux.org/wiki/Installation][wiki]] that will guide a
 33user throughout the installation and post-installation processes, as well as
 34various other articles and guides.
 35
 36To install Alpine, find an appropriate [[https://alpinelinux.org/downloads/][image to download]] and flash it to a USB
 37(Universal Serial Bus) using software such as Rufus or Etcher. I opted to use
 38the Standard image for my x86_{64} architecture.
 39
 40Once the USB is ready, plug it into the machine and reboot. Note that you may
 41have to use a key such as =Esc= or =F1-12= to access the boot menu. The Alpine
 42Linux terminal will load quickly and for a login.
 43
 44To log in to the installation image, use the =root= account; there is no
 45password. Once logged-in, execute the setup command:
 46
 47#+begin_src sh
 48setup-alpine
 49#+end_src
 50
 51The setup script will ask a series of questions to configure the system. Be sure
 52to answer carefully or else you may have to re-configure the system after boot.
 53
 54- *Keyboard Layout*: Local keyboard language and usage mode, e.g., us and variant
 55  of us-nodeadkeys.
 56- *Hostname*: The name for the computer.
 57- *Network*: For example, automatic internet protocol (IP) address discovery
 58  with the Dynamic Host Configuration Protocol (DHCP) protocol.
 59- *DNS (Domain Name System)*: DNS servers to query. For privacy reasons, it is
 60  NOT recommended to route every local request to servers like Google's
 61  8.8.8.8.
 62- *Timezone
 63- *Proxy*: Proxy server to use for accessing the web. Use =none= for direct
 64  connections to the internet.
 65- *Mirror*: From where to download packages. Choose the organization you trust
 66  giving your usage patterns to.
 67- *SSH (Secure Shell Protocol)*: Remote access server. =Openssh= is part of the
 68  default install image. Use =none= to disable remote login, e.g. on laptops.
 69- *NTP (Network Time Protocol)*: Client used for keeping the system clock in
 70  sync with a time-server. Package =chrony= is part of the default install
 71  image.
 72- *Disk Mode*: Select between diskless (=none=), =data= or =sys=, as described
 73  above.
 74
 75Once the setup script is finished, be sure to reboot the machine and remove the
 76USB device.
 77
 78#+begin_src sh
 79reboot
 80#+end_src
 81
 82** Post-Installation
 83
 84There are many things you can do once your Alpine Linux system is up and
 85running, and it largely depends on what you'll use the machine for. I'm going to
 86walk through my personal post-installation setup for my web server.
 87
 881. Upgrade the System
 89
 90   First, login as =root= in order to update and upgrade the system:
 91
 92   #+begin_src sh
 93   apk -U upgrade
 94   #+end_src
 95
 962. Adding a User
 97
 98   I needed to add a user so that I don't need to log in as root. Note that if
 99   you're used to using the =sudo= command, you will now need to use the =doas=
100   command on Alpine Linux.
101
102   #+begin_src sh
103   apk add doas
104   adduser <username>
105   adduser <username> wheel
106   #+end_src
107
108   You can now log out and log back in using the newly-created user:
109
110   #+begin_src sh
111   exit
112   #+end_src
113
1143. Enable Community Packages
115
116   In order to install more common packages that aren't found in the =main=
117   repository, you will need to enable the =community= repository:
118
119   #+begin_src sh
120   doas nano /etc/apk/repositories
121   #+end_src
122
123   Uncomment the community line for whichever version of Alpine you're running:
124
125   #+begin_src sh
126   /media/usb/apks
127   http://dl-cdn.alpinelinux.org/alpine/v3.16/main
128   http://dl-cdn.alpinelinux.org/alpine/v3.16/community
129   #http://dl-cdn.alpinelinux.org/alpine/edge/main
130   #http://dl-cdn.alpinelinux.org/alpine/edge/community
131   #http://dl-cdn.alpinelinux.org/alpine/edge/testing
132   #+end_src
133
1344. Install Required Packages
135
136   Now that the community packages are available, you can install any packages
137   you need. In my case, I installed the web server packages I need for my
138   services:
139
140   #+begin_src sh
141   doas apk add nano nginx docker docker-compose ufw
142   #+end_src
143
1445. SSH
145
146   If you didn't install OpenSSH as part of the installation, you can do so now:
147
148   #+begin_src sh
149   doas apk add openssh
150   #+end_src
151
152   Next, either create a new key or copy your SSH key to the server from your
153   current machines:
154
155   #+begin_src sh
156   # Create a new key
157   ssh-keygen
158   #+end_src
159
160   If you need to copy an existing SSH key from a current machine:
161
162   #+begin_src sh
163   # Copy key from existing machines
164   ssh-copy-id <username>@<ip_address>
165   #+end_src
166
1676. Firewall
168
169   Lastly, I installed =ufw= above as my firewall. To set up, default to deny
170   incoming and allow outgoing connections. Then selectively allow other ports
171   or apps as needed.
172
173   #+begin_src sh
174   doas ufw default deny incoming
175   doas ufw default allow outgoing
176   doas ufw allow SSH
177   doas ufw allow "WWW Full"
178   doas ufw allow 9418 # Git server port
179   #+end_src
180
1817. Change Hostname
182
183   If you don't like the hostname set during installation, you just need to edit
184   two files. First, edit the simple hostname file:
185
186   #+begin_src sh
187   doas nano /etc/hostname
188   #+end_src
189
190   #+begin_src sh
191   <hostname>
192   #+end_src
193
194   Next, edit the =hosts= file:
195
196   #+begin_src sh
197   doas nano /etc/hosts
198   #+end_src
199
200   #+begin_src sh
201   127.0.0.1   <hostname>.local <hostname> localhost.local localhost
202   ::1         <hostname> <hostname>.local
203   #+end_src
204
205* Nginx Web Server
206
207To set up my web server, I simply created the =www= user and created the
208necessary files.
209
210#+begin_src sh
211doas adduser -D -g 'www' www
212mkdir /www
213doas mkdir /www
214doas chown -R www:www /var/lib/nginx/
215doas chown -R www:www /www
216#+end_src
217
218If you're running a simple webroot, you can alter the main =nginx.conf= file.
219Otherwise, you can drop configuration files in the following directory. You
220don't need to enable or symlink the configuration file like you do in other
221systems.
222
223#+begin_src sh
224doas nano /etc/nginx/http.d/example_website.conf
225#+end_src
226
227Once the configuration is set and pointed at the =/www= directory to serve
228files, enable the Nginx service:
229
230#+begin_src sh
231# Note that 'default' must be included or Nginx will not start on boot
232doas rc-update add nginx default
233#+end_src
234
235* Docker Containers
236
237Docker works exactly the same as other systems. Either execute a =docker run=
238command or create a =docker-compose.yml= file and do =docker-compose up -d=.
239
240* Git Server
241
242I went in-depth on how to self-host a git server in another post: [[https://cleberg.net/blog/git-server.html][Self-Hosting
243Guide: Git & cGit]].
244
245However, there are a few differences with Alpine. First note that in order to
246change the =git= user's shell, you must do a few things a little different:
247
248#+begin_src sh
249doas apk add libuser
250doas touch /etc/login.defs
251doas mkdir /etc/default
252doas touch /etc/default/useradd
253doas lchsh git
254#+end_src
255
256* Thoughts on Alpine
257
258So far, I love Alpine Linux. I have no complaints about anything at this point,
259but I'm not completely finished with the migration yet. Once I'm able to upgrade
260my hardware to a rack-mounted server, I will migrate Plex and Syncthing over to
261Alpine as well - possibly putting Plex into a container or VM.
262
263The performance is stellar, the =apk= package manager is seamless, and system
264administration tasks are effortless. My only regret is that I didn't install
265Alpine sooner.