mirror of
https://github.com/dragonlock2/matthewtran.com.git
synced 2025-10-11 20:17:54 +00:00
wip9
This commit is contained in:
parent
e774f3ebdc
commit
1788061642
1
.gitignore
vendored
1
.gitignore
vendored
@ -6,6 +6,7 @@ __pycache__
|
|||||||
config/server.json
|
config/server.json
|
||||||
config/*.bu
|
config/*.bu
|
||||||
config/*.ign
|
config/*.ign
|
||||||
|
config/*.iso
|
||||||
|
|
||||||
# website
|
# website
|
||||||
website/sendgrid.key
|
website/sendgrid.key
|
||||||
|
57
README.md
57
README.md
@ -14,47 +14,34 @@ Services deployed on [matthewtran.com](https://matthewtran.com).
|
|||||||
|
|
||||||
## setup
|
## setup
|
||||||
|
|
||||||
1. Designate one computer as the configuration server. Create `config/server.json` which contains the configuration for the server to be provisioned. Reference `config/server.default` for fields. Run the following.
|
1. Create `config/server.json` and run `config/provision.py`.
|
||||||
- `config/provision.py`
|
2. On the server to be provisioned, boot a [Fedora CoreOS installation media](https://fedoraproject.org/coreos/download?stream=stable) and run the install command.
|
||||||
2. Create a [Fedora CoreOS](https://fedoraproject.org/coreos/download?stream=stable) installation media and boot it on the server to be provisioned. Run the following on it and reboot.
|
3. To configure the OpenWrt router, run `/opt/router.py --provision <interface>` on the server. Then reboot the router and server.
|
||||||
- `sudo coreos-installer install /dev/<boot drive> --ignition-url http://<config server ip>/server.ign --insecure-ignition`
|
4. Add the following DNS entries at the registrar.
|
||||||
|
|
||||||
## update
|
|
||||||
|
|
||||||
quick dev => scp dockerfiles => rebuild locally
|
|
||||||
final dev => reprovision + wipe home so images rebuilds
|
|
||||||
logs => sudo -u game podman logs container
|
|
||||||
|
|
||||||
|
|
||||||
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`.
|
|
||||||
- Add an SSH key if you need remote access, setup will disable password authentication.
|
|
||||||
- Clone this repo and `cd` into it.
|
|
||||||
2. Set up the server.
|
|
||||||
- `scripts/setup_server.py`
|
|
||||||
3. Set up the OpenWrt 24.10 router. Copy SSH keys first to make it easier. Use a strong root password.
|
|
||||||
- `scripts/setup_router.py <interface>`
|
|
||||||
4. Reboot the router and server.
|
|
||||||
5. Configure, build, and start services.
|
|
||||||
- Create `website/sendgrid.key` with a [SendGrid API key](https://app.sendgrid.com/settings/api_keys).
|
|
||||||
- Create `terraria/config.txt` and `terraria/password.txt` if needed.
|
|
||||||
- Create `nas/mounts.json` which contains a list of `"<name>":"<directory>"` for the SMB share.
|
|
||||||
- Create `nas/users.json` which contains a list of `"<user>":"<password>"` for the SMB share.
|
|
||||||
- `scripts/setup_repo.py`
|
|
||||||
- Restore backups if needed. Make sure to set correct ownership. For example, `chown -R 2000:2000 website/gitea`.
|
|
||||||
- `docker compose build`
|
|
||||||
- `docker compose up -d`
|
|
||||||
6. Optionally, add additional drives. This script formats the drive as LUKS/BTRFS with the key file stored in `/opt/luks` and auto-mounts on boot. Make sure to backup the key file elsewhere.
|
|
||||||
- `scripts/setup_drive.py <drive> <mount>`
|
|
||||||
7. Optionally, run `scripts/setup_peer.py <name>` for each WireGuard client.
|
|
||||||
8. Optionally, add the following DNS entries at the registrar.
|
|
||||||
| hosts | type | data |
|
| hosts | type | data |
|
||||||
| ----------------------- | ------ | ------------------------ |
|
| ----------------------- | ------ | ------------------------ |
|
||||||
| `@`, `git`, `wg`, `www` | `A` | `<public IPv4>` |
|
| `@`, `git`, `wg`, `www` | `A` | `<public IPv4>` |
|
||||||
| `@`, `git`, `www` | `AAAA` | `<delegated prefix>::69` |
|
| `@`, `git`, `www` | `AAAA` | `<delegated prefix>::69` |
|
||||||
| `wg` | `AAAA` | `<delegated prefix>::1` |
|
| `wg` | `AAAA` | `<delegated prefix>::1` |
|
||||||
|
5. Optionally, run `config/peer.py` for each WireGuard client.
|
||||||
|
|
||||||
## backup
|
## development
|
||||||
|
|
||||||
|
1. For quick iteration, run `config/update.py`. This copies over sources, rebuilds images, and restarts containers.
|
||||||
|
2. After development, it's best to reprovision (see above) with `wipe=false` for drives you want to keep. Then run `/opt/router.py` on the server and reboot.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## maintenance
|
||||||
|
|
||||||
|
logs => sudo -u game podman logs container
|
||||||
|
TODO mdadm status? backup?
|
||||||
|
|
||||||
Run `scripts/backup.py` and save the resultant `data.zip` somewhere. Also run the following commands for BTRFS maintenance. I should probably automate this.
|
Run `scripts/backup.py` and save the resultant `data.zip` somewhere. Also run the following commands for BTRFS maintenance. I should probably automate this.
|
||||||
```
|
```
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/sudo /usr/bin/python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
@ -14,3 +14,10 @@ if __name__ == "__main__":
|
|||||||
"website/gitea",
|
"website/gitea",
|
||||||
], check=True)
|
], check=True)
|
||||||
shutil.chown(out, os.getlogin(), os.getlogin())
|
shutil.chown(out, os.getlogin(), os.getlogin())
|
||||||
|
|
||||||
|
# TODO backup and scp
|
||||||
|
# TODO restore
|
||||||
|
# fix permissions
|
||||||
|
# no wipe folders we didn't save
|
||||||
|
# may need to chown 777 for gitea
|
||||||
|
# TODO router wipe + peer.py
|
@ -3,7 +3,7 @@
|
|||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
from ipaddress import ip_address, ip_network
|
from ipaddress import ip_address, ip_network
|
||||||
from setup_router import WG_IPV4, WG_IPV6, run, key
|
from router import WG_IPV4, WG_IPV6, run, key
|
||||||
|
|
||||||
def ips():
|
def ips():
|
||||||
try:
|
try:
|
@ -2,7 +2,11 @@
|
|||||||
|
|
||||||
import base64
|
import base64
|
||||||
import json
|
import json
|
||||||
|
import http.server
|
||||||
|
import os
|
||||||
import secrets
|
import secrets
|
||||||
|
import socket
|
||||||
|
import socketserver
|
||||||
import subprocess
|
import subprocess
|
||||||
import yaml
|
import yaml
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@ -40,8 +44,8 @@ PORTS = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def check_keys():
|
def check_keys():
|
||||||
if "home_key" not in cfg["core"]:
|
if "stash_key" not in cfg["core"]:
|
||||||
print(f'cfg["core"]["home_key"] doesn\'t exist, try "{base64.b64encode(secrets.token_bytes(64)).decode("utf-8")}"')
|
print(f'cfg["core"]["stash_key"] doesn\'t exist, try "{base64.b64encode(secrets.token_bytes(64)).decode("utf-8")}"')
|
||||||
exit(1)
|
exit(1)
|
||||||
for i, d in enumerate(cfg["drives"]):
|
for i, d in enumerate(cfg["drives"]):
|
||||||
if "key" not in d:
|
if "key" not in d:
|
||||||
@ -58,11 +62,11 @@ def add_root_drive():
|
|||||||
{
|
{
|
||||||
"number": 4,
|
"number": 4,
|
||||||
"label": "root",
|
"label": "root",
|
||||||
"size_mib": 16384,
|
"size_mib": 65536,
|
||||||
"resize": True,
|
"resize": True,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "home",
|
"label": "stash",
|
||||||
"size_mib": 0,
|
"size_mib": 0,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -78,10 +82,10 @@ def add_root_drive():
|
|||||||
"clevis": { "tpm2": True },
|
"clevis": { "tpm2": True },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "home",
|
"name": "stash",
|
||||||
"device": "/dev/disk/by-partlabel/home",
|
"device": "/dev/disk/by-partlabel/stash",
|
||||||
"wipe_volume": cfg["core"]["home_wipe"],
|
"wipe_volume": cfg["core"]["stash_wipe"],
|
||||||
"key_file": { "inline": base64.b64decode(cfg["core"]["home_key"]) },
|
"key_file": { "inline": base64.b64decode(cfg["core"]["stash_key"]) },
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
"filesystems": [
|
"filesystems": [
|
||||||
@ -92,14 +96,20 @@ def add_root_drive():
|
|||||||
"label": "root",
|
"label": "root",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "/var/home",
|
"path": "/var/mnt/stash",
|
||||||
"device": "/dev/mapper/home",
|
"device": "/dev/mapper/stash",
|
||||||
"format": "xfs",
|
"format": "ext4",
|
||||||
"wipe_filesystem": cfg["core"]["home_wipe"],
|
"wipe_filesystem": cfg["core"]["stash_wipe"],
|
||||||
"with_mount_unit": True,
|
"with_mount_unit": True,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
"directories": [],
|
"directories": [
|
||||||
|
{
|
||||||
|
"path": f"/var/mnt/stash",
|
||||||
|
"user": { "name": "core" },
|
||||||
|
"group": { "name": "core" },
|
||||||
|
},
|
||||||
|
],
|
||||||
"files": [],
|
"files": [],
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,6 +162,7 @@ def add_packages():
|
|||||||
"ExecStart=/usr/bin/rpm-ostree install -y --allow-inactive " + " ".join([
|
"ExecStart=/usr/bin/rpm-ostree install -y --allow-inactive " + " ".join([
|
||||||
"avahi",
|
"avahi",
|
||||||
"htop",
|
"htop",
|
||||||
|
"python3",
|
||||||
"vim",
|
"vim",
|
||||||
]),
|
]),
|
||||||
"ExecStart=/bin/touch /etc/rpm/%N.stamp",
|
"ExecStart=/bin/touch /etc/rpm/%N.stamp",
|
||||||
@ -228,6 +239,11 @@ def copy_source():
|
|||||||
"user": { "name": user },
|
"user": { "name": user },
|
||||||
"group": { "name": user },
|
"group": { "name": user },
|
||||||
})
|
})
|
||||||
|
but["storage"]["files"].append({
|
||||||
|
"path": "/var/opt/router.py",
|
||||||
|
"mode": 0o755,
|
||||||
|
"contents": { "inline": open("config/router.py", "rb").read() },
|
||||||
|
})
|
||||||
|
|
||||||
def build_images():
|
def build_images():
|
||||||
but["storage"]["directories"].append({ "path": "/etc/containers/systemd/users" })
|
but["storage"]["directories"].append({ "path": "/etc/containers/systemd/users" })
|
||||||
@ -365,17 +381,17 @@ if __name__ == "__main__":
|
|||||||
run_containers()
|
run_containers()
|
||||||
advertise_services()
|
advertise_services()
|
||||||
|
|
||||||
|
# generate ignition file
|
||||||
# TODO update router scripts bc DUID => make fixed??
|
|
||||||
# TODO script to backup => restore backup if desired => fix permissions
|
|
||||||
# may need to chown 777 for gitea restore
|
|
||||||
# TODO generate ISO, else nginx if --insecure
|
|
||||||
# TODO full wipe test (wipefs all) => check folder permissions secure
|
|
||||||
|
|
||||||
|
|
||||||
with open("config/server.bu", "w") as f:
|
with open("config/server.bu", "w") as f:
|
||||||
f.write(yaml.dump(but, sort_keys=False))
|
f.write(yaml.dump(but, sort_keys=False))
|
||||||
subprocess.check_output(["butane", "-p", "-s", "-o", "config/server.ign", "config/server.bu"])
|
subprocess.check_output(["butane", "-p", "-s", "-o", "config/server.ign", "config/server.bu"])
|
||||||
|
|
||||||
print("NOTE - TPM may need to be cleared after enough provisions.")
|
# host ignition file
|
||||||
|
ip = socket.gethostbyname(socket.gethostname())
|
||||||
print("WARNING - Using unencrypted connections without authentication, ensure LAN is secure!")
|
print("WARNING - Using unencrypted connections without authentication, ensure LAN is secure!")
|
||||||
|
print("NOTE - TPM may need to be cleared after enough provisions.")
|
||||||
|
print(f"NOTE - Run \"sudo coreos-installer install /dev/<boot drive> --ignition-url http://{ip}/server.ign --insecure-ignition\"")
|
||||||
|
print("NOTE - Starting HTTP server, ctrl-c to exit...")
|
||||||
|
os.chdir("config")
|
||||||
|
with socketserver.TCPServer(("", 80), http.server.SimpleHTTPRequestHandler) as httpd:
|
||||||
|
httpd.serve_forever()
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import argparse
|
||||||
import hashlib
|
import hashlib
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
|
||||||
|
|
||||||
DP_LEN = 64 # xfinity delegated prefix length
|
DP_LEN = 64 # xfinity delegated prefix length
|
||||||
WRT_ULA = "fd16:8f4d:f516::" # OpenWrt random
|
WRT_ULA = "fd16:8f4d:f516::" # OpenWrt random
|
||||||
@ -30,7 +30,19 @@ def key():
|
|||||||
return (pub.decode("utf-8"), priv.decode("utf-8"))
|
return (pub.decode("utf-8"), priv.decode("utf-8"))
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
ETH = sys.argv[1] # e.g. enp5s0
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument("--provision", type=str, help="network interface to set static IP for, e.g. enp5s0")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
# update static IP
|
||||||
|
if args.provision is None:
|
||||||
|
run([
|
||||||
|
f"uci set dhcp.@host[0].duid='{duid()}'",
|
||||||
|
"uci commit dhcp",
|
||||||
|
"service dnsmasq restart",
|
||||||
|
"service odhcpd restart",
|
||||||
|
])
|
||||||
|
exit(0)
|
||||||
|
|
||||||
# basic setup
|
# basic setup
|
||||||
run([
|
run([
|
||||||
@ -43,8 +55,7 @@ if __name__ == "__main__":
|
|||||||
# static IP
|
# static IP
|
||||||
run([
|
run([
|
||||||
"uci add dhcp host",
|
"uci add dhcp host",
|
||||||
"uci set dhcp.@host[-1].name='matt-ryzen'",
|
f"uci set dhcp.@host[-1].mac='{mac(args.provision)}'",
|
||||||
f"uci set dhcp.@host[-1].mac='{mac(ETH)}'",
|
|
||||||
f"uci set dhcp.@host[-1].ip='{IPV4}'",
|
f"uci set dhcp.@host[-1].ip='{IPV4}'",
|
||||||
f"uci set dhcp.@host[-1].duid='{duid()}'",
|
f"uci set dhcp.@host[-1].duid='{duid()}'",
|
||||||
f"uci set dhcp.@host[-1].hostid='{IPV6}'",
|
f"uci set dhcp.@host[-1].hostid='{IPV6}'",
|
@ -4,8 +4,8 @@
|
|||||||
"ssh_keys": [
|
"ssh_keys": [
|
||||||
"ssh-ed25519 AAAA..."
|
"ssh-ed25519 AAAA..."
|
||||||
],
|
],
|
||||||
"home_key": "<LUKS key>",
|
"stash_key": "<LUKS key>",
|
||||||
"home_wipe": false,
|
"stash_wipe": false,
|
||||||
"data_dir": "/var/home/core/matthewtrancom_data"
|
"data_dir": "/var/home/core/matthewtrancom_data"
|
||||||
},
|
},
|
||||||
"drives": [
|
"drives": [
|
@ -19,7 +19,7 @@ update() {
|
|||||||
sleep 86400
|
sleep 86400
|
||||||
}
|
}
|
||||||
update &
|
update &
|
||||||
./ip.py &
|
python3 ip.py &
|
||||||
|
|
||||||
# run server
|
# run server
|
||||||
nginx -c ~/server.conf
|
nginx -c ~/server.conf
|
||||||
|
Loading…
x
Reference in New Issue
Block a user