From c31504656805531cdaec46724ad49cb1f11e8fba Mon Sep 17 00:00:00 2001 From: Daniel Lovegrove Date: Sun, 3 Aug 2025 11:08:24 -0500 Subject: [PATCH] Add non-root config, clean up README --- contrib/podman-systemd/README.md | 135 +++++++++++++++++- ....container => copyparty-nonroot.container} | 14 +- contrib/podman-systemd/copyparty.conf | 2 +- contrib/podman-systemd/copyparty.container | 55 +++++++ 4 files changed, 194 insertions(+), 12 deletions(-) rename contrib/podman-systemd/{copyparty-root.container => copyparty-nonroot.container} (70%) create mode 100644 contrib/podman-systemd/copyparty.container diff --git a/contrib/podman-systemd/README.md b/contrib/podman-systemd/README.md index 2faab18c..340d9f4a 100644 --- a/contrib/podman-systemd/README.md +++ b/contrib/podman-systemd/README.md @@ -1,8 +1,8 @@ # copyparty with Podman and Systemd -Use this configuration is if you want to run copyparty in a Podman container, with the reliability of running the container under a systemd service. +Use this configuration if you want to run copyparty in a Podman container, with the reliability of running the container under a systemd service. -Documentation for `.container` files can be found in the [Container unit](https://docs.podman.io/en/latest/markdown/podman-systemd.unit.5.html#container-units-container) docs. Systemd cannot does not understand `.container` files natively, so Podman converts these to `.service` files with a [systemd-generator](https://www.freedesktop.org/software/systemd/man/latest/systemd.generator.html). This process is transparent, but sometimes needs to be debugged in case your `.container` file is malformed. There are instructions to debug the systemd generator below. +Documentation for `.container` files can be found in the [Container unit](https://docs.podman.io/en/latest/markdown/podman-systemd.unit.5.html#container-units-container) docs. Systemd cannot does not understand `.container` files natively, so Podman converts these to `.service` files with a [systemd-generator](https://www.freedesktop.org/software/systemd/man/latest/systemd.generator.html). This process is transparent, but sometimes needs to be debugged in case your `.container` file is malformed. There are instructions to debug the systemd generator in the Troubleshooting section below. To run copyparty in this way, you must already have podman installed. To install Podman, see: https://podman.io/docs/installation @@ -10,26 +10,29 @@ There is a sample configuration file in the same directory as this file (`copypa ## Run the container as root -It's simplest, but less secure to run the container as the root user. I'd recommend trying to get it to run this way before trying to run it as non-root. +Running the container as the root user is easy to set up, but less secure. There are instructions in the next section to run the container as a rootless user if you'd rather run the container like that. -First, change this line in the `copyparty-root.container` to reflect the directory you want to share. By default, it shares `/mnt/` but you'll probably want to change this. +First, change this line in the `copyparty.container` file to reflect the directory you want to share. By default, it shares `/mnt/` but you'll probably want to change that. ``` +# Change /mnt to something you want to share Volume=/mnt:/w:z ``` -Note that you can change the owner and group of this share by changing the `uid:` and `gid:` of the volume in `copyparty.conf`, but for simplicity let's assume you want it to be owned by `root:root`. +Note that you can select the owner and group of this volume by changing the `uid:` and `gid:` of the volume in `copyparty.conf`, but for simplicity let's assume you want it to be owned by `root:root`. To install and start copyparty with Podman and systemd as the root user, run the following: ```shell sudo mkdir -pv /etc/systemd/container/ /etc/copyparty/ -sudo cp -v copyparty-root.container /etc/systemd/containers/copyparty.container +sudo cp -v copyparty.container /etc/systemd/containers/copyparty.container sudo cp -v copyparty.conf /etc/copyparty/ sudo systemctl daemon-reload -sudo systemctl enable --now copyparty +sudo systemctl start copyparty ``` +Note: You can't "enable" this kind of Podman service. The `[Install]` section of the `.container` file effectively handles enabling the service so that it starts when the server reboots. + You can see the status of the service with: ```shell @@ -45,8 +48,126 @@ sudo podman logs -f copyparty sudo journalctl -a -f -u copyparty ``` +## Run the container as a non-root user + +This configuration is more secure, but is more involved and requires ensuring files have proper permissions. You will need a root user account to do some of this setup. + +First, you need a user to run the container as. In this example we'll create a "podman" user with UID=1001 and GID=1001. + +```shell +sudo groupadd -g 1001 podman +sudo useradd -u 1001 -m podman +sudo usermod -aG podman podman +sudo loginctl enable-linger podman +# Set a strong password for this user +sudo -u podman passwd +``` + +The `enable-linger` command allows the podman user to run systemd user services that persist even when the user is not logged in. You could use a user that already exists in the system to run this service as, just make sure to run `loginctl enable-linger USERNAME` for that user. + +Next, change these lines in the `copyparty.container` file to reflect the config directory and the directory you want to share. By default, the config shares `/home/podman/copyparty/sharing/` but you'll probably want to change this: + +``` +# Change to reflect your non-root user's home directory +Volume=/home/podman/copyparty/config:/cfg:z + +# Change to the directory you want to share +Volume=/home/podman/copyparty/sharing:/w:z +``` + +Make sure the podman user has read/write access to both of these directories. + +Next, **log in to the server as the podman user**. + +To install and start copyparty as the non-root podman user, run the following: + +```shell +mkdir -pv /home/podman/.config/containers/systemd/ /home/podman/copyparty/config +cp -v copyparty.container /home/podman/.config/containers/systemd/copyparty.container +cp -v copyparty.conf /home/podman/copyparty/config +systemctl --user daemon-reload +systemctl --user start copyparty +``` + +**Important note: Never use `sudo` with `systemctl --user`!** + +You can check the status of the user service with: + +```shell +systemctl --user status copyparty +``` + +You can see (and follow) the logs with: + +```shell +podman logs -f copyparty + +journalctl --user -a -f -u copyparty +``` + +## Troubleshooting + If the container fails to start, and you've modified the `.container` service, it's likely that your `.container` file failed to be translated into a `.service` file. You can debug the podman service generator with this command: ```shell sudo /usr/lib/systemd/system-generators/podman-system-generator --dryrun ``` + +## Allowing Traffic from Outside your Server + +To allow traffic on port 3923 of your server, you should run: + +```shell +sudo firewall-cmd --permanent --add-port=3923/tcp +sudo firewall-cmd --reload +``` + +Otherwise, you won't be able to access the copyparty server from anywhere other than the server itself. + +## Updating copyparty + +To update the container, you can: + +```shell +# If root: +sudo podman pull docker.io/copyparty/ac:latest +sudo systemctl restart copyparty + +# If non-root: +podman pull docker.io/copyparty/ac:latest +systemctl --user restart copyparty +``` + +Or, you can change the pinned version of the image in the `[Container]` section of the `.container` file and run: + +```shell +# If root: +sudo systemctl daemon-reload +sudo systemctl restart copyparty + +# If non-root: +systemctl --user daemon-reload +systemctl --user restart copyparty +``` + +Podman will pull the image you've specified when restarting. If you have it set to `:latest`, Podman does not know to re-pull the container. + +### Enabling auto-update + +Alternatively, you can enable auto-updates by un-commenting this line: + +``` +# AutoUpdate=registry +``` + +You will also need to enable the [podman auto-updater service](https://docs.podman.io/en/latest/markdown/podman-auto-update.1.html) with: + +```shell +# If root: +sudo systemctl enable podman-auto-update.timer podman-auto-update.service + +# If non-root: +systemctl --user enable podman-auto-update.timer podman-auto-update.service +``` + +This works best if you always want the latest version of copyparty. The auto-updater runs once every 24 hours. diff --git a/contrib/podman-systemd/copyparty-root.container b/contrib/podman-systemd/copyparty-nonroot.container similarity index 70% rename from contrib/podman-systemd/copyparty-root.container rename to contrib/podman-systemd/copyparty-nonroot.container index 04152392..cdd18027 100644 --- a/contrib/podman-systemd/copyparty-root.container +++ b/contrib/podman-systemd/copyparty-nonroot.container @@ -1,7 +1,12 @@ [Container] -Image=docker.io/copyparty/ac:latest # It's recommended to replace :latest with a specific version +# It's recommended to replace :latest with a specific version +# for example: docker.io/copyparty/ac:latest +Image=docker.io/copyparty/ac:latest ContainerName=copyparty +# Uncomment to enable auto-updates +# AutoUpdate=registry + # Environment variables # enable mimalloc by replacing "NOPE" with "2" for a nice speed-boost (will use twice as much ram) Environment=LD_PRELOAD=/usr/lib/libmimalloc-secure.so.NOPE @@ -12,9 +17,10 @@ Environment=PYTHONUNBUFFERED=1 PublishPort=3923:3923 # Volumes -Volume=/etc/copyparty:/cfg:z -# Change /mnt to the directory you want to share! -Volume=/mnt:/w:z +# Change to reflect your non-root user's home directory +Volume=/home/podman/copyparty/config:/cfg:z +# Change to the directory you want to share +Volume=/home/podman/copyparty/sharing:/w:z # Give the container time to stop in case the thumbnailer is still running. # It's allowed to continue finishing up for 10s after the shutdown signal, give it a 5s buffer diff --git a/contrib/podman-systemd/copyparty.conf b/contrib/podman-systemd/copyparty.conf index bcb643cf..350adaae 100644 --- a/contrib/podman-systemd/copyparty.conf +++ b/contrib/podman-systemd/copyparty.conf @@ -28,7 +28,7 @@ [/] # create a volume at "/" (the webroot), which will - /mnt # share the contents of the "/mnt" folder + /w # share the contents of the "/w" folder accs: rw: * # everyone gets read-write access, but rwmda: ed # the user "ed" gets read-write-move-delete-admin diff --git a/contrib/podman-systemd/copyparty.container b/contrib/podman-systemd/copyparty.container new file mode 100644 index 00000000..adc2473c --- /dev/null +++ b/contrib/podman-systemd/copyparty.container @@ -0,0 +1,55 @@ +[Container] +# It's recommended to replace :latest with a specific version +# for example: docker.io/copyparty/ac:1.18.9 +Image=docker.io/copyparty/ac:latest +ContainerName=copyparty + +# Uncomment to enable auto-updates +# AutoUpdate=registry + +# Environment variables +# enable mimalloc by replacing "NOPE" with "2" for a nice speed-boost (will use twice as much ram) +Environment=LD_PRELOAD=/usr/lib/libmimalloc-secure.so.NOPE +# ensures log-messages are not delayed (but can reduce speed a tiny bit) +Environment=PYTHONUNBUFFERED=1 + +# Ports +PublishPort=3923:3923 + + +# Volumes (PLEASE LOOK!) + +# Rootful setup: +# Leave as-is +# Non-root setup: +# Change /etc/copyparty to /home//copyparty/config +Volume=/etc/copyparty:/cfg:z + +# Rootful setup: +# Change /mnt to the directory you want to share +# Non-root setup: +# Change /mnt to something owned by your user, e.g., /home//copyparty/sharing:/w:z +Volume=/mnt:/w:z + + +# Give the container time to stop in case the thumbnailer is still running. +# It's allowed to continue finishing up for 10s after the shutdown signal, give it a 5s buffer +StopTimeout=15 + +# hide it from logs with "/._" so it matches the default --lf-url filter +HealthCmd="wget --spider -q 127.0.0.1:3923/?reset=/._" +HealthInterval=1m +HealthTimeout=2s +HealthRetries=5 +HealthStartPeriod=15s + +[Unit] +After=default.target + +[Install] +# Start by default on boot +WantedBy=default.target + +[Service] +# Give the container time to start in case it needs to pull the image +TimeoutStartSec=600