README.md (10083B)
1 # aetherscale 2 3 aetherscale is small hobby project to create a hosting environment that can 4 be controlled with an API. I just want to have some fun and 5 dive deeper into Linux tooling (networking, virtualization and so on) and 6 into distributed applications. I do not think that this will become 7 production-ready at any point. 8 9 This is developed along with 10 [a blog tutorial series about scalable computing](https://blog.stefan-koch.name/2020/11/22/programming-cloud-hosting-python-rabbitmq-qemu) 11 which I am currently writing. 12 13 ## Installation 14 15 I recommend installation of the package in a virtual environment for 16 easy removal and to avoid conflicts with system-wide packages: 17 18 ```bash 19 git clone https://github.com/aufziehvogel/aetherscale 20 cd aetherscale 21 virtualenv venv && source venv/bin/activate 22 pip install . 23 ``` 24 25 aetherscale must be able to adjust networking interfaces and routing. For 26 more information on why it uses the following permission management, refer 27 to the section *Rationale* below. 28 29 To allow aetherscale to adjust networking and routing, give the user that 30 is running aetherscale sudo permissions for the `ip` program, i.e. add the 31 following line to your `visudo`: 32 33 ``` 34 youruser ALL=(ALL) NOPASSWD: /usr/bin/ip, /usr/bin/radvd 35 ``` 36 37 Currently, aetherscale also requires radvd for IPv6 in VPNs, but this will 38 change in the future. We will expect users to handle their VPN completely 39 on their own, i.e. there must be a DHCP or Router Advertisment server inside 40 the VPN. 41 42 43 ## Getting Started 44 45 Each VM is booted from a base image, which has to be created in advance. 46 To create a base image download an 47 installation ISO for your favourite Linux distribution and install it to a 48 qcow2 file with the following commands (and follow the installation 49 instructions inside the started QEMU VM). When you're finished just shutdown 50 the VM. 51 52 ```bash 53 BASE_IMAGE=base-image-name.qcow2 54 ISO=your-distribution.iso 55 56 qemu-img create -f qcow2 $BASE_IMAGE 20G 57 qemu-system-x86_64 -cpu host -accel kvm -m 4096 -hda $BASE_IMAGE -cdrom $ISO 58 ``` 59 60 The qcow2 base image must be located inside the 61 `$BASE_IMAGE_FOLDER` directory. This is a configurable environment variable. 62 63 aetherscale expects a bridge network `br0` on the physical ethernet which can 64 be used to attach additional TAP interfaces for VMs. If this interface does not 65 exist, an error will be displayed on startup of the server. Please refer to 66 your network manager's documentation (e.g. ifupdown, systemd-networkd, ...) 67 for instructions on how to create a bridge. For iproute2 I have [a short 68 tutorial on my blog](https://blog.stefan-koch.name/2020/10/25/qemu-public-ip-vm-with-tap). 69 70 To get started it's best to use the HTTP interface of the aetherscale 71 server. While our HTTP implementation 72 does not allow scaling to multiple machines it's a good way to play around 73 with this program. You can start the HTTP server with: 74 75 ```bash 76 aetherscale http 77 ``` 78 79 Once the server is running (on localhost port 5000 in this example) you can 80 create a new VM from the previously created base image and list all 81 VMs with: 82 83 ```bash 84 curl -XPOST -H "Content-Type: application/json" \ 85 -d '{"image": "ubuntu-20.04.1-server-amd64"}' http://localhost:5000/vm 86 87 curl http://localhost:5000/vm 88 ``` 89 90 The base image must be located at 91 `$BASE_IMAGE_FOLDER/ubuntu-20.04.1-server-amd64.qcow2`. 92 93 You can also stop a running VM and start a stopped VM by `PATCH`'ing the 94 VM's REST endpoint with the desired status: 95 96 ```bash 97 curl -XPATCH -H "Content-Type: application/json" \ 98 -d '{"status": "stopped"}' http://localhost:5000/vm/adbvzwdf 99 100 curl -XPATCH -H "Content-Type: application/json" \ 101 -d '{"status": "started"}' http://localhost:5000/vm/adbvzwdf 102 ``` 103 104 Please note that stopping a VM (gracefully) takes some time, so you cannot 105 start it immediately after you have issued a stop request. 106 107 TODO: We might change this interface to 108 [an `actions` endpoint](https://restful-api-design.readthedocs.io/en/latest/methods.html) 109 and treat action requests as an ordered queue of requests. 110 I.e., a stop request immediately followed by a start request should bring 111 the VM down (which might take a few seconds) and afterwards start it again 112 (even if the start request cam in before the VM was completely stopped). 113 114 115 ## Run Tests 116 117 You can run tests with `tox`: 118 119 ```bash 120 tox 121 ``` 122 123 124 ## Overview 125 126 Components which I think would be interesting to develop are: 127 128 - Firewall (probably nftables, so that I can learn nftables) 129 - Virtual Private Networks (probably tinc) 130 - Virtual Servers (probably qemu) 131 - IPv6-only intranet to learn IPv6 132 133 ### Creating VMs 134 135 When you want to create a new VM, you have to use a *base image*. This is an 136 already prepared QEMU image in `qcow2` format that will be used to start your 137 machine. 138 139 You can define a custom script that is run on the first start of the machine. 140 This can be used to install additional software or to configure software. 141 The init-script is run by systemd and its output can be monitored with 142 143 ```bash 144 journalctl -f -u aetherscale-init 145 ``` 146 147 Execution after the first boot of the machine is prohibited by a conditions 148 file (cf. in `/etc/systemd/system/aetherscale-init.service`). If you 149 want to run your script during another boot, you can delete the conditions 150 file. 151 152 ## Architecture 153 154 My idea is that all requests to the system go through a central message 155 broker. Handlers will then pick up these tasks and perform the work. 156 157 Each request can have the name of a unique channel for responses. The sender 158 of a message can open a channel with this name on the broker and will receive 159 responses. This is useful if you have to wait until another component has 160 performed their work. 161 162 ### Files created by aetherscale 163 164 aetherscale creates different files for VM management in your filesystem. 165 My goal is to make aetherscale so simple that you can always fix or extend 166 stuff manually. This section lists all relevant files that aetherscale creates. 167 The aetherscale configuration directory is a config variable and thus might 168 be changed. In this section it is refered to as `$CONFIG_DIR`, its default 169 location is `~/.config/aetherscale`. 170 171 For each VM aetherscale creates: 172 173 - if required by the VM, networking setup scripts for the VM at 174 `$CONFIG_DIR/networking/*-setup.sh` as well as teardown scripts at 175 `$CONFIG_DIR/networking/*-teardown.sh` 176 - a systemd user service file at 177 `~/.config/systemd/user/aetherscale-vm-*.service` 178 179 TODOs for VM networking: 180 181 - TODO: Structure files into subfolders, e.g. `CONFIG/vm/vm-ID/IFACE-setup.sh`? 182 183 For each VPN network aetherscale creates: 184 185 - a tincd configuration folder structure at 186 `$CONFIG_DIR/tinc` with one subfolder per VPN network 187 - setup and teardown scripts for the host networking rules at 188 `$CONFIG_DIR/networking/network-*-setup.sh` and 189 `$CONFIG_DIR/networking/network-*-teardown.sh` 190 - a systemd user service file at 191 `~/.config/systemd/aetherscale-tincd-*.service` 192 193 TODOs for VPN networking: 194 195 - TODO: Rename prefix to `vpn` instead of `network` 196 - TODO: Structure files into subfolders, e.g. `CONFIG/vpn/vpn-abc/setup.sh`? 197 198 199 ### Computing 200 201 Stuff I use for computing (and thus have learnt something about so far): 202 203 - Qemu 204 - software bridging with `ip` (for public and private IPs) 205 - VDE could also be relevant, but currently out of scope 206 - layer-2 VPN with tinc 207 - `libguestfs` for analyzing and changing images 208 - IPv6, radvd 209 210 211 ## Rationale 212 213 ### Operating System Changes 214 215 I am trying to design aetherscale to run without root permissions for 216 as much as possible. 217 For some actions more permissions than a standard user usually has are 218 needed, though. This section will guide you through all of the changes 219 required to allow aetherscale itself to run as a standard user. 220 221 #### Networking 222 223 aetherscale has to adjust your networking in order to expose the VMs to the 224 network. I decided to setup a bridge network for the VMs to join with 225 `iproute2`. 226 227 Bridge networks are used in two different situations: 228 229 1. When exposing the VM to the public internet 230 2. When establishing a VPN network between multiple VMs 231 232 In both cases we use the `iproute2` (`ip`) utility. To allow aetherscale to 233 run as a non-root user while still having access to networking changes, I 234 decided to use `sudo` and allow rootless access to `ip`. 235 236 For VPN there currently is one more change needed (but this is only 237 temporary). To auto-configure IPv6 addresses of VPNs inside 238 the guest VM we use IPv6 Router Advertisement messages. We run a `radvd` 239 server that sends out the prefixes for IPv6 addresses. `radvd` also requires 240 root permissions (to be exact it requires `CAP_NET_RAW` permissions). 241 242 To allow these calls you have to enable passwordless sudo permissions with 243 the following entry in `visudo`: 244 245 ``` 246 youruser ALL=(ALL) NOPASSWD: /usr/bin/ip, /usr/bin/radvd 247 ``` 248 249 Having `radvd` on the host machine is only a temporary solution. In a real 250 setup, the VPN has to manage the internal IP addresses itself. We will 251 probably provide an init-script template for a machine that does this. 252 253 Requiring `sudo` is not a perfect solution but Linux capabilities inheritance to 254 subprocesses seems quite complicated, and without inheritance we'd have to grant 255 `CAP_NET_ADMIN` to both `ip` and `tincd`. This might be undesired, because 256 then any user can change network devices. Another option could be to 257 assign `CAP_NET_ADMIN` to the user running aetherscale, but this seems to 258 [require changes to pam](https://unix.stackexchange.com/questions/454708/how-do-you-add-cap-sys-admin-permissions-to-user-in-centos-7) 259 and still seems to require inheritable capabilities to be set on each 260 binary that is to be executed. 261 While this in my opinion would be a reasonable choice for a production 262 program, it feels too heavy for a proof-of-concept tool. 263 264 265 ## Contribution 266 267 If you want to contribute you can: 268 269 - create some steampunk artwork for this project :) 270 - think about what else could be interesting to implement (especially if 271 it runs as a daemon it should be based on well-established Linux technology 272 that runs without babysitting it all day long) 273 - create a routine for simple setup of the root installation steps