I have two remote VPS's running:
* `nalpine-uno`.
* `nalpine-dos`.
Add your public SSH keys when initially setting up the VPS.
# SSH Daemon
For optimal security, password-based authentication through SSH should be disabled. The only way you should be able to connect to the server is with public SSH keys.
```bash
# /etc/ssh/sshd_config
AuthorizedKeysFile .ssh/authorized_keys
KbdInteractiveAuthentication no
PasswordAuthentication no
PermitEmptyPasswords no
PubkeyAuthentication yes
PrintMotd no
UsePAM yes
```
To allow `sshd` to bind to a private IP address which may not be available when it starts, you can enable non-local IP bindings like so:
```bash
$ sudo echo "net.ipv4.ip_nonlocal_bind=1" >> /etc/sysctl.d/99-nonlocal-bind.conf
$ sudo sysctl -f /etc/sysctl.d/99-nonlocal-bind.conf
```
```bash
$ chmod 700 ~/.ssh
$ chmod 600 ~/.ssh/authorized_keys
$ chmod go-w ~
```
# WireGuard
WireGuard is a communication protocol for creating Virtual Private Networks (VPNs).
## WireGuard "Server" [(1)](https://wiki.alpinelinux.org/wiki/Configure_a_Wireguard_interface_(wg))
### What is it?
The word "server" is in quotes because WireGuard isn't based on a client-server model. Technically, all devices in a WireGuard network are peers. It's just that in most setups, one peer acts like a hub for other WireGuard peers to connect. This is known as a hub and spoke configuration.
### How do you set it up?
#### Step 1 - Download the required packages
There are three packages to install:
```bash
$ sudo apk add wireguard-tools-wg-quick
$ sudo apk add wireguard-tools-openrc
$ sudo apk add iptables
```
* `wireguard-tools-wg-quick` - This package provides the `wg-quick` program, a script for bringing up and tearing down WireGuard interfaces according configuration files stored in the `/etc/wireguard/` directory. Each file in that directory corresponds to a WireGuard interface.
* `wireguard-tools-openrc` - This package provides OpenRC init scripts that automatically run `wg-quick` with a specific configuration.
* `iptables` - This package provides the `iptables` program to manage packet filtering.
#### Step 2 - Generate a key pair
WireGuard is based on public-key cryptography. Each peer has a public key and a private key. The public key is shared with other peers and the private key is kept secure.
These keys are generated with the `wg` program. This one-line command from the Gentoo Wiki article on WireGuard will generate a public key and private key, and save them to their own respective files.
```bash
$ $(umask 077; wg genkey | tee privatekey | wg pubkey > publickey)
```
#### Step 3 - Write the WireGuard interface configuration
As mentioned before, the configuration files for WireGuard are stored in the `/etc/wireguard/` directory. Each file corresponds to a WireGuard interface. These files are named like so:
```
/etc/wireguard/<name of the interface>.conf
```
##### How are WireGuard interfaces named?
The names for WireGuard interfaces are generally prefixed with `wg` and end with a number, with that number starting at `0` for the first interface and then incrementing with each additional interface.
> [!example] Example of the path of the configuration file for the first WireGuard interface
> The following file would configure a WireGuard interface named `wg0`, which is often the first WireGuard interface on a system:
> ```
> /etc/wireguard/wg0.conf
> ```
##### How are WireGuard IP addresses configured? [(1)](https://en.wikipedia.org/wiki/Private_network)
Since WireGuard is used to create Virtual *Private* Networks (VPNs), the peers in the network all have *private* IP addresses as opposed to public IP addresses. Every peer's IP address is statically assigned through their configuration files.
There are three particular ranges of IP addresses which are designated to be used for private networks. Those are:
1. 192.168.0.0 to 192.168.255.255, or 192.168.0.0/16 - You're likely familiar with these IP addresses because most home networks use these.
2. 172.16.0.0 to 172.31.255.255, or 172.16.0.0/12.
3. 10.0.0.0 to 10.255.255.255, or 10.0.0.0/8.
You may have noticed the /16, /12, and /8 endings on the IP addresses and how they correspond to a range of IP addresses. This notation is called Classless Inter-Domain Routing (CIDR) notation. The number after the slash tells you how many binary digits (bits) at the beginning of the IP address are reserved for the network address. The remaining bits are used as the host address.
A network address is essentially the fixed part of an IP address which identifies the network that some devices are connected to. The host address is the unique part of an IP address that identifies a specific machine (or host) within a network.
* 192.168.0.0/16 - The network address is 192.168. The host address can *theoretically* be any number between 192.168.0.1 and 192.168.255.254. That's 65,536 possible IP addresses.
* 172.16.0.0/12 - The network address is 172.16. The host address can *theoretically* be any address between 172.16.0.1 and 172.31.255.254. That's 1,048,576 possible IP addresses.
* 10.0.0.0/8 - The network address is 10. The host address can *theoretically* be any address between 10.0.0.1 and 10.255.255.254. That's 16,777,216 possible IP addresses.
In most networks, these huge IP address ranges are often split into smaller ranges of IP addresses for organization, isolation, security, and efficiency. The process of splitting up a range of IP addresses is called subnetting.
> [!example] Example of subnetting
> A company might have a very large private network made up of different kinds of devices and several different departments. The private IP address range they're using is 192.168.0.0/16. You could set up subnets of that IP address range like so:
> * 192.168.1.0/24 - The network address is 192.168.1. The host address can *theoretically* be any address between 192.168.1.1 and 192.168.1.255. This could be a subnet specifically for the IT department and their servers, admin PCs, and management tools.
> * 192.168.2.0/24 - The network address is 192.168.2. The host address can *theoretically* be any address between 192.168.2.1 and 192.168.2.254. This could be a subnet specifically for devices in HR.
> [!warning]
> If you decide to use IP addresses between 192.168.0.0 and 192.168.255.255, you need to ensure that it doesn't conflict with any addresses or subnets being used by your local network. To prevent conflicts from happening, use a unique subnet for your WireGuard network which isn't being used on your local network.
>> [!example] Examples of unique private IP address subnets which may avoid conflicts from happening with your local network
> > * 192.168.200.0/24.
> > * 192.168.99.0/24.
##### What is the format of the WireGuard interface configuration file?
There are two sets of options that can be used to configure WireGuard interfaces. The set of options you use is determined by which program you use to start WireGuard: `wg` or `wg-quick`. The program recommended by the WireGuard documentation and the Alpine Linux Wiki is `wg-quick`.
The WireGuard configuration on the server is generally going to follow this format:
```ini
# /etc/wireguard/wg0.conf
[Interface]
Address = .../24
ListenPort = ...
PrivateKey = ...
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE;iptables -A FORWARD -o %i -j ACCEPT
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE;iptables -D FORWARD -o %i -j ACCEPT
[Peer]
PublicKey = ...
AllowedIPs = .../32
```
These are the meanings of each option in the WireGuard configuration:
* `[Interface]` - This block defines the settings for the interface itself.
* `Address` - This is the private, WireGuard-specific IP address of this interface.
* `ListenPort` - This is the port number that the interface is using to listen for WireGuard connections.
* `PrivateKey` - This is the private key that will be used by this peer. Copy and paste the key from step 2 in its entirety here.
* `PostUp` and `PostDown` - These are `iptables` commands which allow traffic from the WireGuard subnet (`wg0`) to be forwarded to the LAN subnet on the `eth0` interface.
* `[Peer]` - This block defines the settings for a WireGuard client that connects to the server. There should be a `[Peer]` block for every WireGuard client you intend to have connect to the server.
* `PublicKey` - This is the public key of the client which was generated in step 4 of the previous section. Just copy and paste the key in its entirety here.
* `AllowedIPs` - This is the private, WireGuard-specific IP address you want assigned to this client. This is the private, WireGuard-specific IP address of the WireGuard client. This value should match whatever was set for the `WireGuard.Address` setting on the client.
Make sure to change the permissions to only allow the root user to read the WireGuard configuration file:
```bash
$ sudo chmod 600 /etc/wireguard/wg0.conf
```
#### Step 4 - Exchange public keys between the server and all of the clients
Copy the public key of the WireGuard server and paste it in the `/var/lib/connman-vpn/*.config` configuration file on every client.
Copy the public key of every client and paste it in the appropriate `[Peer]` block in the `/etc/wireguard/wg0.conf` configuration file.
#### Step 5 - Enable and start the WireGuard OpenRC service
```bash
$ sudo ln -s /etc/init.d/wg-quick /etc/init.d/wg-quick.wg0
$ sudo rc-update add wg-quick.wg0
$ sudo rc-service wg-quick.wg0 start
```
## WireGuard Clients - ConnMan [(1)](https://wiki.gentoo.org/wiki/WireGuard)
The clients, which are the machines that will be connecting to the WireGuard server, are going to be my desktop and laptop.
Both systems run Gentoo and use ConnMan as their network manager. ConnMan supports VPN connections like WireGuard with some additional configuration.
### How do you set it up?
#### Step 1 - Check the version of ConnMan
The version of ConnMan on the stable branch, which is version 1.43, seems to have a bug which causes ConnMan to immediately crash due to a segmentation fault if you try to connect a VPN. At least, it crashed when I tried using my WireGuard configuration. Unmasking the testing (unstable) branch version of ConnMan, which is version 1.44, fixed this issue on my system.
#### Step 2 - Unmask the testing branch for ConnMan
To allow Portage to install the testing (unstable) version of `net-misc/connman`, add the following to `/etc/portage/package.accept_keywords`:
```bash
# /etc/portage/package.accept_keywords/connman
net-misc/connman ~amd64
```
#### Step 3 - Update ConnMan and install WireGuard tools
Before emerging ConnMan, you also have to make sure the `wireguard` USE flag is set so that the package builds with WireGuard support. There are some other USE flags I've set for personal preference.
```bash
# /etc/portage/package.use/connman
# ConnMan
net-misc/connman bluetooth debug -iwd policykit wireguard
```
Emerge `net-misc/connman` so that it builds with the new USE flags, and at the same time install `net-vpn/wireguard-tools`:
```bash
$ sudo emerge -av net-misc/connman net-vpn/wireguard-tools
```
Make sure that the correct version of ConnMan is now installed by running:
```bash
$ /usr/sbin/connmand -v
```
If the version is listed as 1.44, that means the package was successfully installed.
#### Step 4 - Generate a key pair
WireGuard uses key pairs to encrypt network traffic. These keys are generated using the `wg genkey` and `wg pubkey` commands.
```bash
# This is a nice one-line command that saves a private key and its respective public key to their own files.
$ $(umask 077; wg genkey | tee privatekey | wg pubkey > publickey)
```
> [!warning]
> It should go without saying, but don't expose your keys, especially your private key. After setting up the WireGuard configurations on the client-side and server-side, delete the files created for the keys and make sure permissions are properly set on the WireGuard configuration files to prevent them from being read by non-root users.
#### Step 5 - Write the WireGuard configuration for ConnMan
ConnMan looks for VPN configurations in the `/var/lib/connman-vpn/` directory by default. Files in that directory have to end with `.config` for them to be read.
```ini
[provider_wireguard]
Type = WireGuard
Name = ...
Host = ...
WireGuard.Address = .../24
WireGuard.ListenPort = ...
WireGuard.PrivateKey = ...
WireGuard.PublicKey = ...
WireGuard.AllowedIPs = .../24
WireGuard.EndpointPort = ...
WireGuard.PersistentKeepalive = ...
```
* `Type` - ConnMan supports a few types of VPN connections. Since we're configuring a WireGuard VPN connection, we need to set this to `WireGuard`.
* `Name` - This can be any name you want for the connection. This is the name in the left-most column when you run `connmanctl services`.
* `Host` - This is the IP address of the WireGuard server. It needs to be accessible from your client.
* WireGuard-specific settings.
* `WireGuard.Address` - This is the private, WireGuard-specific IP address you want assigned to this client.
* `WireGuard.ListenPort` - This is the port number that ConnMan will use to listen for WireGuard connections. The default port number for WireGuard is 51820.
* `WireGuard.PrivateKey` - This is the private key of the client which was generated in step 4. Just copy and paste the key in its entirety here.
* `WireGuard.PublicKey` - This is the public key of the WireGuard server. This key will be generated once you configure the WireGuard server. Once you get it, just copy and paste it here.
* `WireGuard.AllowedIPs` - This is IP address subnet which will be allowed to go through the WireGuard interface. If you want outbound network traffic to any IP address to go through the WireGuard interface, you would set it to `0.0.0.0/0, ::/0`. If you only want outbound traffic to private IP address subnets to go through the WireGuard interface, you would set it to something like `10.0.0.0/24` or `172.16.0.0/24`.
* `WireGuard.EndpointPort` - This is the port number that the WireGuard server is using to listen for WireGuard connections.
* `WireGuard.PersistentKeepalive` - This setting controls how many seconds should pass before ConnMan sends a keepalive packet to the WireGuard server. Specifying this optional because WireGuard is actually designed to be silent when not in use. A very common value for this is `25`.
Make sure to change the permissions to only allow the root user to read the WireGuard configuration file:
```bash
$ sudo chmod 600 /var/lib/connman-vpn/*.config
```
#### Step 6 - Restart ConnMan
```bash
$ sudo rc-service connman restart
```
### Is there any more configuration?
Depending on what you intend to use WireGuard for, there may be one more additional step you need to do.
By default, ConnMan sets the default network interface to be the WireGuard interface `wg0`. If your intention is to use WireGuard as a VPN to access the Internet from another machine, then no more configuration is necessary.
> [!warning]
> Don't turn on auto connect for the VPN if you're going to route all of your network traffic through it. For some reason, the Ethernet or Wi-Fi services don't
In my case, I don't actually want all of my client's network traffic routed through the WireGuard server. I just want to be able to refer to the server using a private IP address regardless of what network the client is physically connected to. All other network traffic should still be routed as if WireGuard wasn't connected. This is called split routing.
### How do you set up split routing?
#### Step 1 - Connect the VPN
ConnMan will create a directory for every service you connect to in order to store persistent settings like the SSID, passphrase, IPv4 and IPv6 settings, and more. These directories are stored in `/var/lib/connman/`. Each directory will have a `data` file and a `settings` file.
The same is true for VPN connections. The configuration for the VPN service itself isn't generated until you connect the VPN at least once.
```bash
$ connmanctl
connmanctl> services
connmanctl> connect vpn_<rest of service name>
Connected vpn_<rest of service name>
connmanctl> exit
```
#### Step 2 - Edit the configuration for the VPN service
Edit the `/var/lib/connman/vpn_*/settings` configuration file by setting the `SplitRouting` option to `true`:
```bash
# /var/lib/connman/vpn_*/settings
# ...
SplitRouting=true
# ...
```
You can set the `AutoConnect` option to true if you want the client to automatically connect to the WireGuard server.
#### Step 3 - Restart ConnMan
After that has been set, restart ConnMan:
```bash
$ sudo rc-service connman restart
```
#### Step 4 - Verify that `wg0` isn't the default interface
You can use the `ip route` command to examine the routing table.
> [!example] Example of output from the `ip route` command which shows that WireGuard is turned on with split routing
> If the first line in the output of the command is your actual Ethernet or Wi-Fi interface, that means WireGuard has been configured to only allow traffic for private IP addresses to be routed through the WireGuard interface.
> ```bash
> $ ip route
> default via 192.168.3.1 dev wlp3s0
> 1.1.1.1 via 192.168.3.1 dev wlp3s0
> 8.8.8.8 via 192.168.3.1 dev wlp3s0
> 10.0.0.0/24 via 10.0.0.3 dev wg0 scope link
> 10.0.0.0/24 dev wg0 proto kernel scope link src 10.0.0.3
> (redacted IP address) via 192.168.3.1 dev wlp3s0
> 192.168.3.0/24 dev wlp3s0 proto kernel scope link src 192.168.3.86
> 192.168.3.1 dev wlp3s0 scope link
> ```
> [!example] Example of output from the `ip route` command which shows that WireGuard is turned on without split routing
> If the first line in the output of the command is the WireGuard interface, that means all network traffic is being routed through it and not split. This is fine if that's what your goal is.
> ```bash
> $ ip route
> default dev wg0 scope link
> default via 192.168.3.1 dev wlp3s0 metric 4294964223
> 1.1.1.1 via 192.168.3.1 dev wlp3s0
> 8.8.8.8 via 192.168.3.1 dev wlp3s0
> 10.0.0.0/24 dev wg0 proto kernel scope link src 10.0.0.3
> (redacted IP address) via 192.168.3.1 dev wlp3s0
> 192.168.3.0/24 dev wlp3s0 proto kernel scope link src 192.168.3.86
> 192.168.3.1 dev wlp3s0 scope link
> ```
### How do you use it?
To connect to the WireGuard server using ConnMan:
```bash
$ connmanctl
connmanctl> services
...
# If you turned on auto connect for the VPN service, it should automatically be connected. Otherwise, you can connect to it with the connect command.
connmanctl> connect vpn_<rest of service name>
Connected vpn_<rest of service name>
connmanctl> exit
```
To test the connection to the WireGuard server:
```bash
$ ping <private IP address of the WireGuard server>
```
# Containers
```bash
# Create a user for every service.
$ sudo useradd -m git
$ sudo useradd -m -r -s /usr/sbin/nologin portal
$ sudo useradd -m -r -s /usr/sbin/nologin sync
$ sudo useradd -m -r -s /usr/sbin/nologin www
```
```bash
# Enable the main edge repository.
$ echo "http://dl-cdn.alpinelinux.org/alpine/edge/main" >> /etc/apk/repositories
# Upgrade OpenRC.
$ sudo apk upgrade openrc
# Confirm that OpenRC is now at version 0.60 at least.
$ openrc --version
# Multi-plex the user service with symlinks to enable user-specific services.
$ sudo ln -s /etc/init.d/user /etc/init.d/user.git
$ sudo ln -s /etc/init.d/user /etc/init.d/user.portal
$ sudo ln -s /etc/init.d/user /etc/init.d/user.sync
$ sudo ln -s /etc/init.d/user /etc/init.d/user.www
```
```bash
$ sudo apk add podman
```
```bash
# /etc/subuid
git:100000:65536
portal:165536:65536
sync:231072:65536
www:296608:65536
# /etc/subgid
git:100000:65536
portal:165536:65536
sync:231072:65536
www:296608:65536
```
```bash
$ sudo rc-service cgroups start
```