This commit is contained in:
Matthew Tran 2025-05-03 03:24:40 -07:00
parent 32366a797e
commit 1846d973a3
3 changed files with 85 additions and 21 deletions

View File

@ -21,9 +21,12 @@ Services deployed on [matthewtran.com](https://matthewtran.com).
## update ## update
quick dev => scp dockerfiles => rebuild locally
final dev => reprovision
TODO fix setup_router DUID suff => may need to reset after each provision...
1. Install [Ubuntu Desktop 24.04.1 LTS](https://ubuntu.com/download/desktop) with TPM-backed FDE. Server currently has a [bug](https://bugs.launchpad.net/ubuntu/+source/cryptsetup/+bug/1980018) that makes TPM-backed FDE hard. 1. Install [Ubuntu Desktop 24.04.1 LTS](https://ubuntu.com/download/desktop) with TPM-backed FDE. Server currently has a [bug](https://bugs.launchpad.net/ubuntu/+source/cryptsetup/+bug/1980018) that makes TPM-backed FDE hard.
- You may need to manually enable IPv6 on the network connection. Use `Automatic` not `Automatic, DHCP only`. - You may need to manually enable IPv6 on the network connection. Use `Automatic` not `Automatic, DHCP only`.
@ -60,7 +63,3 @@ Run `scripts/backup.py` and save the resultant `data.zip` somewhere. Also run th
btrfs device stats <mount> btrfs device stats <mount>
btrfs scrub start -B <mount> btrfs scrub start -B <mount>
``` ```
## security
To protect against vulnerabilities, all services run as non-root users inside containers that are on separate networks by function and have all capabilities dropped. These non-root users have a UID that doesn't exist on the host and a GID that maps to their function. Hopefully, even in the event of a full container compromise and root escalation, there is little damage an attacker can do. The main security hole left is containers accessing the LAN and host, AppArmor might help with this.

View File

@ -6,5 +6,13 @@
], ],
"var_key": "<LUKS key>", "var_key": "<LUKS key>",
"var_wipe": false "var_wipe": false
} },
"drives": [
{
"devices": ["/dev/sda"],
"key": "<LUKS key>",
"name": "stuff",
"wipe": false
}
]
} }

View File

@ -1,6 +1,8 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import base64
import json import json
import secrets
import subprocess import subprocess
import yaml import yaml
@ -11,6 +13,15 @@ if __name__ == "__main__":
"version": "1.6.0", "version": "1.6.0",
} }
# recommend keys if needed
if "var_key" not in cfg["core"]:
print(f'cfg["core"]["var_key"] doesn\'t exist, try "{base64.b64encode(secrets.token_bytes(64)).decode("utf-8")}"')
exit(1)
for i, d in enumerate(cfg["drives"]):
if "key" not in d:
print(f'cfg["drives"][{i}]["key"] doesn\'t exist, try "{base64.b64encode(secrets.token_bytes(64)).decode("utf-8")}"')
exit(1)
# configure root drive # configure root drive
but["storage"] = { but["storage"] = {
"disks": [ "disks": [
@ -31,33 +42,68 @@ if __name__ == "__main__":
], ],
}, },
], ],
"raid": [],
"luks": [
{
"name": "root",
"label": "luks-root",
"device": "/dev/disk/by-partlabel/root",
"wipe_volume": True,
"clevis": { "tpm2": True },
},
{
"name": "var",
"device": "/dev/disk/by-partlabel/var",
"wipe_volume": cfg["core"]["var_wipe"],
"key_file": { "inline": base64.b64decode(cfg["core"]["var_key"]) },
},
],
"filesystems": [ "filesystems": [
{ {
"device": "/dev/disk/by-partlabel/root", "device": "/dev/mapper/root",
"format": "btrfs", "format": "xfs",
"wipe_filesystem": True, "wipe_filesystem": True,
"label": "root", "label": "root",
}, },
{ {
"path": "/var", "path": "/var",
"device": "/dev/disk/by-partlabel/var", "device": "/dev/mapper/var",
"format": "btrfs", "format": "xfs",
"wipe_filesystem": cfg["core"]["var_wipe"], "wipe_filesystem": cfg["core"]["var_wipe"],
"with_mount_unit": True, "with_mount_unit": True,
}, },
], ],
"files": [],
"directories": [],
} }
# set hostname # add additional drives
but["storage"]["files"] = [ for d in cfg["drives"]:
{ raid = len(d["devices"]) > 1
"path": "/etc/hostname", if raid:
"mode": 0o644, but["storage"]["raid"].append({
"contents": { "name": d["name"],
"inline": cfg["core"]["hostname"], "level": "raid1",
}, "devices": d["devices"],
}, })
] but["storage"]["luks"].append({
"name": d["name"],
"device": f"/dev/md/{d["name"]}" if raid else d["devices"][0],
"wipe_volume": d["wipe"],
"key_file": { "inline": base64.b64decode(d["key"]) },
})
but["storage"]["filesystems"].append({
"path": f"/var/mnt/{d["name"]}",
"device": f"/dev/mapper/{d["name"]}",
"format": "ext4",
"wipe_filesystem": d["wipe"],
"with_mount_unit": True,
})
but["storage"]["directories"].append({
"path": f"/var/mnt/{d["name"]}",
"user": { "name": "core" },
"group": { "name": "core" },
})
# add SSH keys # add SSH keys
assert(len(cfg["core"]["ssh_keys"]) > 0) assert(len(cfg["core"]["ssh_keys"]) > 0)
@ -90,6 +136,7 @@ if __name__ == "__main__":
"ExecStart=/usr/bin/rpm-ostree install -y --allow-inactive " + " ".join([ "ExecStart=/usr/bin/rpm-ostree install -y --allow-inactive " + " ".join([
"avahi", "avahi",
"htop", "htop",
"vim",
]), ]),
"ExecStart=/bin/touch /etc/rpm/%N.stamp", "ExecStart=/bin/touch /etc/rpm/%N.stamp",
"ExecStart=/bin/systemctl --no-block reboot", "ExecStart=/bin/systemctl --no-block reboot",
@ -100,10 +147,20 @@ if __name__ == "__main__":
], ],
} }
# set hostname
but["storage"]["files"].append({
"path": "/etc/hostname",
"mode": 0o644,
"contents": { "inline": cfg["core"]["hostname"] },
})
# allow unprivileged port access
but["storage"]["files"].append({
"path": "/etc/sysctl.d/99-unprivileged-ports.conf",
"mode": 0o644,
"contents": { "inline": "net.ipv4.ip_unprivileged_port_start=80" },
})
# TODO encrypt /var w/ key (root w/ tpm)
# TODO add additional drives (raid?)
# TODO make server build images on first boot? # TODO make server build images on first boot?
# TODO serve backup.zip to restore on first boot? only if wipe specified # TODO serve backup.zip to restore on first boot? only if wipe specified