diff --git a/.gitignore b/.gitignore index 0171851..e6289d8 100644 --- a/.gitignore +++ b/.gitignore @@ -19,13 +19,6 @@ minecraft_bedrock/server.properties # terraria terraria/*.txt - - - - - - # nas -nas/*.json +nas/Dockerfile nas/smb.conf -nas/users.sh diff --git a/README.md b/README.md index 9f0883e..c3bc2e1 100644 --- a/README.md +++ b/README.md @@ -26,8 +26,6 @@ final dev => reprovision + wipe home so images rebuilds logs => sudo -u game podman logs container -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. - 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. diff --git a/config/provision.py b/config/provision.py index 4450eef..a04c1c5 100755 --- a/config/provision.py +++ b/config/provision.py @@ -19,7 +19,7 @@ PORTS = { "web": [ "80:80", # website "443:443", - "2222:2222", # gitea + "2222:22", # gitea ], "monero": [ "18080:18080", # monerod @@ -34,6 +34,9 @@ PORTS = { "19133:19133/udp", "7777:7777", # terraria ], + "nas": [ + "445:445", # nas + ], } def check_keys(): @@ -145,6 +148,7 @@ def add_packages(): "[Service]", "Type=oneshot", "RemainAfterExit=yes", + f"ExecStart=/usr/bin/usermod -a -G {",".join(UIDS.keys())} core", "ExecStart=/usr/bin/rpm-ostree install -y --allow-inactive " + " ".join([ "avahi", "htop", @@ -201,26 +205,28 @@ def copy_source(): "user": { "name": "core" }, "group": { "name": "core" }, }) - for i in (f for s in IMAGES.values() for f in s): - but["storage"]["directories"].append({ - "path": str(Path(SOURCE_DIR) / i), - "user": { "name": "core" }, - "group": { "name": "core" }, - }) - for f in Path(i).glob("**/*"): - if f.is_dir(): - but["storage"]["directories"].append({ - "path": str(Path(SOURCE_DIR) / f), - "user": { "name": "core" }, - "group": { "name": "core" }, - }) - else: - but["storage"]["files"].append({ - "path": str(Path(SOURCE_DIR) / f), - "contents": { "inline": open(f, "rb").read() }, - "user": { "name": "core" }, - "group": { "name": "core" }, - }) + for user in IMAGES: + for img in IMAGES[user]: + but["storage"]["directories"].append({ + "path": str(Path(SOURCE_DIR) / img), + "mode": 0o770, + "user": { "name": user }, + "group": { "name": user }, + }) + for f in Path(img).glob("**/*"): + if f.is_dir(): + but["storage"]["directories"].append({ + "path": str(Path(SOURCE_DIR) / f), + "user": { "name": user }, + "group": { "name": user }, + }) + else: + but["storage"]["files"].append({ + "path": str(Path(SOURCE_DIR) / f), + "contents": { "inline": open(f, "rb").read() }, + "user": { "name": user }, + "group": { "name": user }, + }) def build_images(): but["storage"]["directories"].append({ "path": "/etc/containers/systemd/users" }) @@ -240,7 +246,10 @@ def create_pods(): for user in IMAGES: but["storage"]["files"].append({ "path": f"/etc/containers/systemd/users/{UIDS[user]}/{user}.pod", - "contents": { "inline": "[Pod]\n" + "\n".join([f"PublishPort={p}" for p in PORTS[user]])} + "contents": { "inline": "\n".join([ + "[Pod]", + *[f"PublishPort={p}" for p in PORTS[user]], + ])}, }) def create_folders(): @@ -250,16 +259,45 @@ def create_folders(): "group": { "name": "core" }, }) for user in IMAGES: + but["storage"]["directories"].append({ + "path": str(Path(cfg["core"]["data_dir"]) / user), + "mode": 0o770, + "user": { "name": user }, + "group": { "name": user }, + }) for img in IMAGES[user]: but["storage"]["directories"].append({ - "path": str(Path(cfg["core"]["data_dir"]) / img), + "path": str(Path(cfg["core"]["data_dir"]) / user / img), "user": { "name": user }, "group": { "name": user }, }) + for mnt in cfg["nas"]["mounts"]: + but["storage"]["directories"].append({ + "path": str(Path(cfg["nas"]["mounts"][mnt]) / "share"), + "mode": 0o770, + "user": { "name": "nas" }, + "group": { "name": "nas" }, + }) def run_containers(): for user in IMAGES: for img in IMAGES[user]: + env = [] + if img == "gitea": + env.extend([ + "Environment=GITEA__server__SSH_PORT=2222", + "Environment=GITEA__service__DISABLE_REGISTRATION=true", + "Environment=GITEA__openid__ENABLE_OPENID_SIGNIN=false", + "Environment=GITEA__openid__ENABLE_OPENID_SIGNUP=false", + ]) + + vols = [f"Volume={str(Path(cfg["core"]["data_dir"]) / user / img)}:/data:z"] + if user == "nas": + vols.extend([ + f"Volume={str(Path(cfg["nas"]["mounts"][mnt]) / "share")}:/mnt/{mnt}:z" + for mnt in cfg["nas"]["mounts"] + ]) + but["storage"]["files"].append({ "path": f"/etc/containers/systemd/users/{UIDS[user]}/{img}.container", "contents": { "inline": "\n".join([ @@ -267,7 +305,8 @@ def run_containers(): f"ContainerName={img}", f"Image={img}.build", f"Pod={user}.pod", - f"Volume={str(Path(cfg["core"]["data_dir"]) / img)}:/data:z", + *env, + *vols, "[Install]", "WantedBy=default.target", ])} @@ -299,13 +338,16 @@ if __name__ == "__main__": run_containers() - # TODO add nas - # TODO restrict access to source code... - # add core to all groups => owned by users only access by them too - # TODO script to backup => restore backup if desired - + # 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 # 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: f.write(yaml.dump(but, sort_keys=False)) subprocess.check_output(["butane", "-p", "-s", "-o", "config/server.ign", "config/server.bu"]) diff --git a/config/server.default b/config/server.default index 8159ce7..def418c 100644 --- a/config/server.default +++ b/config/server.default @@ -32,5 +32,13 @@ "size": 3, "difficulty": 2 } + }, + "nas": { + "users": { + "matt": "password" + }, + "mounts": { + "stuff": "/var/mnt/stuff" + } } } \ No newline at end of file diff --git a/config/update.py b/config/update.py index 4c9c628..e37a060 100755 --- a/config/update.py +++ b/config/update.py @@ -20,6 +20,9 @@ IMAGES = { "minecraft_bedrock", "terraria", ], + "nas": [ + "nas", + ], } def generate(cfg): @@ -46,6 +49,19 @@ def generate(cfg): with open("terraria/password.txt", "w") as f: f.write(cfg["terraria"]["password"]) + # nas + shutil.copy("nas/Dockerfile.template", "nas/Dockerfile") + shutil.copy("nas/smb.conf.template", "nas/smb.conf") + with open("nas/Dockerfile", "a") as f: + for user in cfg["nas"]["users"]: + p = cfg["nas"]["users"][user] + f.write(f"RUN useradd -M -s /bin/false {user}\n") + f.write(f"RUN echo \"{p}\\n{p}\\n\" | pdbedit -s smb.conf -a {user}\n") + with open("nas/smb.conf", "a") as f: + for mnt in cfg["nas"]["mounts"]: + f.write(f"[{mnt}]\n") + f.write(f"path = /mnt/{mnt}\n\n") + def run(cmds): try: subprocess.check_output(["ssh", f"core@{cfg["core"]["hostname"]}.local", ";".join(cmds)], stderr=subprocess.STDOUT) @@ -64,6 +80,7 @@ if __name__ == "__main__": # 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... # run builds for user in IMAGES: diff --git a/gitea/Dockerfile b/gitea/Dockerfile index bc0bb43..0a0d43b 100644 --- a/gitea/Dockerfile +++ b/gitea/Dockerfile @@ -1,7 +1 @@ FROM docker.io/gitea/gitea:1.23.7 - -# After boot, recommended to modify the following in gitea/conf/app.ini -# SSH_LISTEN_PORT=2222 -# DISABLE_REGISTRATION=true -# ENABLE_OPENID_SIGNIN=false -# ENABLE_OPENID_SIGNUP=false diff --git a/nas/Dockerfile b/nas/Dockerfile deleted file mode 100644 index 46ab3da..0000000 --- a/nas/Dockerfile +++ /dev/null @@ -1,20 +0,0 @@ -FROM ubuntu:24.04 - -ENV TZ=America/Los_Angeles -RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone - -RUN apt-get update && apt-get -y upgrade -RUN apt-get install -y samba - -# create required files and user -RUN groupadd -g 2003 me && useradd -u 2003 -g 2003 -m me -USER me -WORKDIR /home/me -RUN mkdir share samba samba/log samba/lock samba/state samba/cache samba/pid samba/private samba/ncalrpc -COPY --chown=me:me smb.conf entry.sh ./ - -# create additional users -USER root -COPY users.sh ./ -RUN /bin/sh users.sh && rm users.sh -USER me diff --git a/nas/Dockerfile.template b/nas/Dockerfile.template new file mode 100644 index 0000000..04f8bfb --- /dev/null +++ b/nas/Dockerfile.template @@ -0,0 +1,15 @@ +FROM ubuntu:24.04 + +ENV TZ=America/Los_Angeles +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +RUN apt-get update && apt-get -y upgrade +RUN apt-get install -y samba + +WORKDIR /root + +COPY smb.conf entry.sh ./ + +CMD ["/bin/bash", "/root/entry.sh"] + +# create users diff --git a/nas/entry.sh b/nas/entry.sh index 35f285c..4311ace 100644 --- a/nas/entry.sh +++ b/nas/entry.sh @@ -1,6 +1,6 @@ #!/bin/sh -smbd -s smb.conf -l=/home/me/samba/log -trap 'echo "stopping smbd..."' TERM +smbd -s smb.conf +trap 'echo "stopping smbd..."' SIGTERM SIGINT tail -f /dev/null & wait $! diff --git a/nas/base.conf b/nas/smb.conf.template similarity index 77% rename from nas/base.conf rename to nas/smb.conf.template index bbe17c1..c496f9d 100644 --- a/nas/base.conf +++ b/nas/smb.conf.template @@ -1,6 +1,6 @@ [global] workgroup = WORKGROUP -smb ports = 8445 +smb ports = 445 load printers = no disable spoolss = yes @@ -22,19 +22,12 @@ client smb3 signing algorithms = AES-128-GMAC AES-128-CMAC HMAC-SHA256 client signing = required client ipc signing = required -lock directory = /home/me/samba/lock -state directory = /home/me/samba/state -cache directory = /home/me/samba/cache -pid directory = /home/me/samba/pid -private dir = /home/me/samba/private -ncalrpc dir = /home/me/samba/ncalrpc - browseable = yes writable = yes create mask = 0660 directory mask = 0770 -force user = me -force group = me +force user = root +force group = root vfs objects = fruit streams_xattr fruit:metadata = stream