A UGREEN NAS running UGOS is a competent Linux box: x86_64, Docker installed, SSH available. So the natural assumption is that hosting a small service on it works the way it works anywhere else. Install a runtime, start a process, add a cron entry, done.
It does not. UGOS reserves a lot for its own management layer, and the account you SSH in with is not the account that owns the system. Every one of the four standard moves fails, each in a slightly different way, and none of the error messages tell you what to do instead.
Here is what actually works, and what each wall looks like when you hit it. Almost every guide for this class of appliance is written for Synology, where the answers are different. This one is written from UGOS.
Wall 1: your SSH user cannot use Docker
You will find Docker installed and immediately discover it is not yours to use:
$ docker ps
permission denied while trying to connect to the Docker daemon socket
at unix:///var/run/docker.sock: connect: permission denied
The usual fix is sudo usermod -aG docker $USER. That fails too, because your
account has no sudo, and UGOS does not offer a way to grant either one. Docker
on this appliance is reachable through the desktop UI app and through control
panels like 1Panel, but not from your shell.
What to do instead: skip Docker. This sounds like a downgrade and mostly is not. A container buys you a restart policy, log rotation, and dependency isolation. For a single service with no system dependencies, you can get the first two by other means and do not need the third.
Everything below assumes a plain host process.
Wall 2: your runtime's installer needs unzip, which is absent
Most modern runtimes install with a one-liner that pipes a script into your
shell. On UGOS that script gets some distance and then dies, because the archive
it downloads is a zip and there is no unzip on the system. There is no apt
either — this is an appliance, not a distro.
What to do instead: unpack it on your own machine and copy the binary over. Most runtimes ship a single static binary inside that archive; the installer script is a convenience, not a requirement.
# on your own machine
curl -L -o runtime.zip https://example.com/runtime-linux-x64.zip
unzip runtime.zip
# stream the binary over SSH into place
cat runtime-linux-x64/bin/runtime \
| ssh user@nas 'mkdir -p ~/bin && cat > ~/bin/runtime && chmod +x ~/bin/runtime'
Then add ~/bin to your PATH in ~/.profile. From here on the runtime behaves
completely normally — the only thing missing was the unpacking tool.
The same trick works for any single-binary tool you need on the box.
Wall 3: SSH is not exposed, so plan how you reach the machine
Port 22 is not open to the internet, and it should stay that way. When you are at home this is a non-issue. When you are not, you need a private path in.
The clean answer is a mesh VPN — Tailscale or equivalent — which gives the NAS a
stable private address reachable from your laptop anywhere, with no ports opened
and no dynamic-DNS games. Install it, and ssh user@100.x.y.z works from a
different continent.
Worth knowing before you need it: the UGOS app centre has no web terminal, and the "Terminal" entry in the control panel is only an on/off switch for the SSH service, not a shell. If you lose your private path while away from home, your remaining options are the control panel's scheduled-task feature — which can run a script, so it doubles as a crude remote-execution channel — or waiting until you are back on the LAN. Set the VPN up before you travel, not after.
Wall 4: cron refuses you, and nohup alone is not enough
Two separate problems, usually discovered together.
First, starting a process over SSH and disconnecting kills it unless you detach it properly:
setsid nohup ~/bin/runtime server.js > ~/logs/app.log 2>&1 &
nohup alone survives the hangup signal in most cases; setsid also detaches
the process from the terminal's session, which is what you actually want for
something meant to outlive your shell.
Second, the obvious way to start it at boot is not available:
$ crontab -e
/var/spool/cron: Permission denied
There is no user crontab, and no systemctl --user either.
What to do instead: use the control panel's scheduled tasks. UGOS exposes a task scheduler in its web UI with a run-at-startup trigger, and it will run a shell script as your user. Point it at a small launcher script rather than at the command directly, so you can change how the service starts without going back into the UI:
#!/bin/sh
# ~/apps/myapp/start.sh — kill any previous instance, then start fresh
pkill -f 'runtime server.js'
sleep 1
cd ~/apps/myapp || exit 1
setsid nohup ~/bin/runtime server.js > ~/logs/app.log 2>&1 &
The same script is your deploy step and your restart step, which is one fewer thing to remember.
Deploying updates: tar over SSH
rsync is not present and scp is unreliable here. What works is streaming a
tar through the SSH connection:
tar czf - --exclude=node_modules --exclude=data . \
| ssh user@nas 'mkdir -p ~/apps/myapp && tar xzf - -C ~/apps/myapp'
ssh user@nas '~/apps/myapp/start.sh'
Exclude your data directory explicitly, every time. The one deploy where you forget is the one that overwrites your database with an empty copy from your laptop.
Verify the part everyone skips
Restarting the service proves the service works. It does not prove the thing you actually care about, which is that the NAS comes back on its own after losing power.
So test it: reboot the NAS from the control panel, wait, and check that the service answers without you touching anything.
curl -sI http://<nas-address>:<port>/ | head -1
"It should come back" and "it came back" are different claims. The gap between them is usually a scheduled task that was saved but never enabled, and you would rather find that out now than during a power cut while you are away.
What this gets you
A service running as your own user, started at boot by the appliance's own
scheduler, deployed with one tar command, with no sudo, no Docker, and nothing
installed system-wide. It is less elegant than a container and considerably less
elegant than systemd, but it is entirely within what UGOS will let you do, and
it stays working.
When it's worth paying
Nothing in this article costs money, and for running services at home the free path genuinely goes the whole distance. The appliance is already bought, the software is free, and the constraints are annoying rather than limiting.
The honest limit is not money, it is what a box in your house can promise. One power supply, one internet connection, and no maintenance window that is not your own evening. That is fine for a personal service and fine for a site like this one. The moment something needs to be up while you are asleep, travelling, or moving house, the fix is not a better startup script — it is a machine in a building with a generator, which is where a cheap VPS starts to make sense. I've written about how to tell when you've actually reached that point, because deciding it deliberately beats discovering it during an outage.