diff --git a/config/provision.py b/config/provision.py index a04c1c5..0b824f2 100755 --- a/config/provision.py +++ b/config/provision.py @@ -193,6 +193,7 @@ def add_users(): but["passwd"]["users"].append({ "name": user, "uid": UIDS[user], + "ssh_authorized_keys": cfg["core"]["ssh_keys"], }) but["storage"]["files"].append({ "path": f"/var/lib/systemd/linger/{user}", @@ -312,6 +313,32 @@ def run_containers(): ])} }) +def advertise_services(): + but["storage"]["directories"].extend([ + { "path": "/etc/avahi" }, + { "path": "/etc/avahi/services" }, + ]) + for mnt in cfg["nas"]["mounts"]: + but["storage"]["files"].append({ + "path": f"/etc/avahi/services/nas-{mnt}.service", + "contents": { "inline": "\n".join([ + "", + "", + "", + f" %h - {mnt}", + " ", + " _smb._tcp", + " 445", + " ", + " ", + " _adisk._tcp", + f" dk0=adVN={mnt},adVF=0x82", + " sys=waMa=0,adVF=0x100", + " ", + "", + ])} + }) + if __name__ == "__main__": cfg = json.load(open("config/server.json")) but = { @@ -336,11 +363,9 @@ if __name__ == "__main__": create_pods() create_folders() run_containers() + advertise_services() - # TODO fix update.py ownership - # TODO gen apache services - # 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 diff --git a/config/update.py b/config/update.py index e37a060..cf83a99 100755 --- a/config/update.py +++ b/config/update.py @@ -62,9 +62,9 @@ def generate(cfg): f.write(f"[{mnt}]\n") f.write(f"path = /mnt/{mnt}\n\n") -def run(cmds): +def run(cmds, user="core"): try: - subprocess.check_output(["ssh", f"core@{cfg["core"]["hostname"]}.local", ";".join(cmds)], stderr=subprocess.STDOUT) + subprocess.check_output(["ssh", f"{user}@{cfg["core"]["hostname"]}.local", ";".join(cmds)], stderr=subprocess.STDOUT) except subprocess.CalledProcessError as e: print("\033[31m", end="") print(e.output.decode()) @@ -78,9 +78,10 @@ if __name__ == "__main__": generate(cfg) # copy files - for f in (f for l in IMAGES.values() for f in l): - subprocess.run(["scp", "-r", f, f"core@{cfg["core"]["hostname"]}.local:{SOURCE_DIR}"], check=True) - # TODO should probs chown and chmod correctly... + for user in IMAGES: + for img in IMAGES[user]: + subprocess.run(["scp", "-r", img, f"{user}@{cfg["core"]["hostname"]}.local:{SOURCE_DIR}"], check=True) + run([f"chmod 770 {SOURCE_DIR}/{img}"], user=user) # run builds for user in IMAGES: diff --git a/scripts/setup_drive.py b/scripts/setup_drive.py deleted file mode 100755 index 5eba7b9..0000000 --- a/scripts/setup_drive.py +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/sudo /usr/bin/python3 - -import os -import shutil -import subprocess -import sys -from pathlib import Path - -KEY_DIR = Path("/opt/luks") - -def run(cmd): - subprocess.run(cmd.split(), check=True) - -if __name__ == "__main__": - drive = sys.argv[1] - mount = Path(sys.argv[2]) - key = KEY_DIR / f"{drive}.key" - assert(Path(f"/dev/{drive}").exists()) - assert(not key.exists()) - - # create directories and key - KEY_DIR.mkdir(exist_ok=True) - mount.mkdir(exist_ok=True) - run(f"dd if=/dev/random bs=32 count=1 of={key}") - key.chmod(0o400) - - # format and mount drive - run(f"cryptsetup luksFormat --key-file={key} /dev/{drive}") - run(f"cryptsetup luksOpen --key-file={key} /dev/{drive} {drive}_luks") - run(f"mkfs.btrfs /dev/mapper/{drive}_luks") - run(f"mount /dev/mapper/{drive}_luks {mount}") - shutil.chown(mount, os.getlogin(), "nas") - mount.chmod(0o770) - - # TODO modify /etc/crypttab instead once Ubuntu fixed - with open("/opt/luks.sh", "a") as f: - f.write(f"systemd-cryptsetup attach {drive}_luks /dev/{drive} {key} luks\n") - f.write(f"mount /dev/mapper/{drive}_luks {mount}\n") diff --git a/scripts/setup_repo.py b/scripts/setup_repo.py deleted file mode 100755 index 2e22b2d..0000000 --- a/scripts/setup_repo.py +++ /dev/null @@ -1,95 +0,0 @@ -#!/usr/bin/sudo /usr/bin/python3 - -import json -import os -import shutil -import subprocess -import yaml -from pathlib import Path - -if __name__ == "__main__": - override = {} - - # create folders so containers have access - PATHS = { - "web": [ - "website/certbot", - "website/gitea/config", - "website/gitea/data", - ], - "monero": [ - "monerod/.bitmonero", - "p2pool/cache", - ], - "game": [ - "minecraft/worlds", - "minecraft_bedrock/worlds", - "terraria/worlds", - "terraria/mods", - ] - } - for group in PATHS: - for p in PATHS[group]: - Path(p).mkdir(parents=True, exist_ok=True) - Path(p).chmod(0o775) - shutil.chown(p, user=os.getlogin(), group=group) - - # add users to nas - file = Path("nas/users.json") - script = Path("nas/users.sh") - with script.open("w") as f: - if file.exists(): - users = json.load(file.open()) - for id, user in enumerate(users): - id = 3000 + id - f.writelines(s + "\n" for s in [ - f"groupadd -g {id} {user}", - f"useradd -M -s /bin/false -u {id} -g {id} {user}", - f"su - me -c 'echo \"{users[user]}\\n{users[user]}\\n\" | pdbedit -s smb.conf -a {user}'", - ]) - shutil.chown(script, user=os.getlogin(), group=os.getlogin()) - - # add volumes to nas - file = Path("nas/mounts.json") - serv = Path("/etc/avahi/services") - conf = Path("nas/smb.conf") - shutil.copyfile("nas/base.conf", conf) - shutil.chown(conf, user=os.getlogin(), group=os.getlogin()) - for f in serv.glob("nas-*.service"): - f.unlink() - if file.exists(): - mounts = json.load(file.open()) - with open("nas/smb.conf", "a") as f: - for m in mounts: - f.write(f"[{m}]\n") - f.write(f"path = /home/me/share/{m}\n") - f.write("\n") - override.setdefault("services", {})["nas"] = {"volumes": [f"{mounts[m]}:/home/me/share/{m}" for m in mounts]} - for m in mounts: - with (serv / f"nas-{m}.service").open("w") as f: - f.writelines(s + "\n" for s in [ - "", - "", - "", - f" %h - {m}", - " ", - " _smb._tcp", - " 445", - " ", - " ", - " _adisk._tcp", - f" dk0=adVN={m},adVF=0x82", - " sys=waMa=0,adVF=0x100", - " ", - "", - ]) - subprocess.run(["systemctl", "restart", "avahi-daemon"], check=True) - - # generate compose override - file = Path("compose.override.yml") - if override: - with file.open("w") as f: - yaml.dump(override, f) - shutil.chown(file, user=os.getlogin(), group=os.getlogin()) - else: - file.unlink(True) diff --git a/scripts/setup_server.py b/scripts/setup_server.py deleted file mode 100755 index 45fc11d..0000000 --- a/scripts/setup_server.py +++ /dev/null @@ -1,107 +0,0 @@ -#!/usr/bin/sudo /usr/bin/python3 - -import json -import os -import subprocess -from pathlib import Path - -def run(cmd, capture=False): - if capture: - return subprocess.check_output(cmd.split()) - else: - subprocess.run(cmd.split(), check=True) - -if __name__ == "__main__": - # install dependencies and configure - run("apt update") - run("apt upgrade -y") - run("apt install -y avahi-daemon btrfs-progs openssh-server python-is-python3 python3-pip wireguard zip") - with open("/etc/sysctl.conf", "a+") as f: # enable huge pages for local mining - f.seek(0) - if "vm.nr_hugepages=1280\n" not in f.readlines(): - f.write("vm.nr_hugepages=1280\n") - file = Path("/etc/ssh/sshd_config.d/restrict.conf") # only allow public key login - if not file.exists(): - with file.open("w") as f: - f.write("PasswordAuthentication no\n") - - # install docker and configure - run("snap install docker") - run("addgroup --system docker") - run(f"adduser {os.getlogin()} docker") - with open("/var/snap/docker/current/config/daemon.json", "r+") as f: - cfg = json.load(f) - cfg["ipv6"] = True - cfg["fixed-cidr-v6"] = "fd3a:138e:8fd0:0000::/64" # Docker ULA - f.seek(0) - json.dump(cfg, f, indent=4) - run("systemctl restart snap.docker.dockerd.service") - - try: - run("addgroup --gid 2000 web") - run("addgroup --gid 2001 monero") - run("addgroup --gid 2002 game") - run("addgroup --gid 2003 nas") - run(f"adduser {os.getlogin()} web") - run(f"adduser {os.getlogin()} monero") - run(f"adduser {os.getlogin()} game") - run(f"adduser {os.getlogin()} nas") - except: - pass - - # restrict network access from containers - file = Path("/etc/systemd/system/docker-restrict.service") - if not file.exists(): - with file.open("w") as f: - f.writelines(s + "\n" for s in [ - "[Unit]", - "Description=Restrict Docker network access", - "Before=network.target", - "After=network-pre.target", - "", - "[Service]", - "Type=oneshot", - "ExecStart=/opt/docker-restrict.sh", - "RemainAfterExit=yes", - "", - "[Install]", - "WantedBy=multi-user.target", - ]) - file = Path("/opt/docker-restrict.sh") - if not file.exists(): - with file.open("w") as f: - f.writelines(s + "\n" for s in [ - "#!/bin/sh", - "iptables -N DOCKER-USER || true", - "iptables -I DOCKER-USER -d 10.0.0.0/8 -j DROP", # xfinity gateway - "iptables -I DOCKER-USER -p tcp --dport 22 -j DROP", # SSH - "ip6tables -N DOCKER-USER || true", - "ip6tables -I DOCKER-USER -p tcp --dport 22 -j DROP", # SSH - ]) - file.chmod(0o755) - run("systemctl enable docker-restrict.service") - - # TODO modify /etc/crypttab instead once Ubuntu fixed - file = Path("/etc/systemd/system/luks.service") - if not file.exists(): - with file.open("w") as f: - f.writelines(s + "\n" for s in [ - "[Unit]", - "Description=Mount more LUKS drives", - "After=local-fs.target", - "Requires=local-fs.target", - "", - "[Service]", - "Type=oneshot", - "ExecStart=/opt/luks.sh", - "RemainAfterExit=yes", - "", - "[Install]", - "WantedBy=multi-user.target", - ]) - file = Path("/opt/luks.sh") - if not file.exists(): - with file.open("w") as f: - f.write("#!/bin/sh\n") - file.chmod(0o755) - run("systemctl enable luks.service")