How to use BackInTime with an Ugreen NAS or any other NAS
BackInTime is a very great tool to run incremental backups on Linux. I use it since >10 years and never had issues with it.
I created a docker image which can be run on the remote host (where the backup files are stored). On Synology and Ugreen NAS’s, it can be tricky to set it up correctly. As a better approach I created a pre-configured docker container which handles all that is needed on the remote host.
See https://github.com/caco3/backintime-sshd for up-to-date instructions.
Migration from a Synology NAS
I originally used BackInTime with a Synology NAS and wanted to move the data now to an Ugreen NAS. The transition was not as easy as expected, but I got it working. See below for some guidance.
Moving your data
To move existing backups from my old NAS to the new one, I used following command (using SSH on the old NAS):
rsync -aHr backintime me@192.168.1.8:/volume1/backintime/
which copies all data to the new NAS and preserves the hardllinks.
Making sure the backup uses de-duplication (hardlinks)
After I moved the data to the new NAS and run the first backup, it took forever. I then found out that rsync for some reasons did not use hardlinks for de-duplication. Instead it created a new full backup. I was able to also solve this issue using fclones with the priority „top“. , see https://github.com/bit-team/backintime/issues/2312#issuecomment-3622378794 for details.
You can validate that the hardlinks work using:
> cd /volume1/backintime
> for d in */ ; do ls -li $d/backup/etc/wodim.conf; done
117340170 -rwxrwxrwx 103 backintime users 1343 Jan 9 2007 20120530-213845-751//backup/etc/wodim.conf
[..]
117340170 -rwxrwxrwx 103 backintime users 1343 Jan 9 2007 20251202-221758-751//backup/etc/wodim.conf
The first number is the inode number. If the fales share the same hardlink (thus only use the harddisk space once), they will have the same number.
Note: Pick a file of which you know exists since the first backup and did never change (for me it was /etc/wodim.conf).

Hurra! It works!
First I uninstalled jellyfin and docker as installed by UGREEN for jellyfin.
That installation had a directory called /volume1/docker/configurations with jellyfin stuff in it. I figured I’d better start from scratch. I removed the old /volume1/docker.
Then reinstalled just docker.
Built the project as per your improved instructions.
It started running … continued with your instruction steps:
sshd-1 | [INFO] Applying configuration for ‚root‘ user …
sshd-1 | [INFO] disabled login for user ‚root‘
sshd-1 | [INFO] user ‚root‘ is now LOCKED
sshd-1 |
sshd-1 | [INFO] Applying configuration for additional users …
sshd-1 | [INFO] desired shell is /bin/bash
sshd-1 | [INFO] ‚backintime:1006:100‘
sshd-1 | [WARN] desired GID is already present in system. Using the present group-name – GID: ‚100‘ GNAME: ‚users‘
sshd-1 | [INFO] user ‚backintime‘ created – UID: ‚1006‘ GID: ‚100‘ GNAME: ‚users‘
sshd-1 | [WARN] no SSH authorized_keys found for user ‚backintime‘
sshd-1 |
sshd-1 |
sshd-1 | Server listening on 0.0.0.0 port 22.
sshd-1 | Server listening on :: port 22.
Edited the authorized_keys file and stopped the container. The enabled it again.
sshd-1 | Received signal 15; terminating.
sshd-1 | [INFO] Applying configuration for ‚root‘ user …
sshd-1 | [INFO] disabled login for user ‚root‘
sshd-1 | [INFO] user ‚root‘ is now LOCKED
sshd-1 |
sshd-1 | [INFO] Applying configuration for additional users …
sshd-1 | [INFO] desired shell is /bin/bash
sshd-1 | [INFO] ‚backintime:1006:100‘
sshd-1 | [WARN] desired GID is already present in system. Using the present group-name – GID: ‚100‘ GNAME: ‚users‘
sshd-1 | [WARN] desired USER_NAME is already present in system. Skipping creation – USER_NAME: ‚backintime‘
sshd-1 | [INFO] copied /conf.d/authorized_keys/backintime to /home/backintime/.ssh/authorized_k
eys
sshd-1 | [INFO] set mod 0600 on /home/backintime/.ssh/authorized_keys
sshd-1 |
sshd-1 |
sshd-1 | Server listening on 0.0.0.0 port 22.
sshd-1 | Server listening on :: port 22.
Here I went ahead of your steps and tried making a new profile in backintime …
sshd-1 | ssh_dispatch_run_fatal: Connection from UNKNOWN port -1: Broken pipe [preauth]
sshd-1 | Connection closed by 192.168.5.2 port 35612 [preauth]
sshd-1 | Connection closed by 192.168.5.2 port 35614 [preauth]
sshd-1 | Connection closed by 192.168.5.2 port 35616 [preauth]
sshd-1 | ssh_dispatch_run_fatal: Connection from UNKNOWN port -1: Broken pipe [preauth]
sshd-1 | Connection closed by 192.168.5.2 port 37496 [preauth]
sshd-1 | Connection closed by 192.168.5.2 port 37504 [preauth]
sshd-1 | Connection closed by 192.168.5.2 port 37506 [preauth]
sshd-1 | ssh_dispatch_run_fatal: Connection from UNKNOWN port -1: Broken pipe [preauth]
sshd-1 | Connection closed by 192.168.5.2 port 42952 [preauth]
sshd-1 | Connection closed by 192.168.5.2 port 42968 [preauth]
sshd-1 | Connection closed by 192.168.5.2 port 42980 [preauth]
sshd-1 | ssh_dispatch_run_fatal: Connection from UNKNOWN port -1: Broken pipe [preauth]
sshd-1 | Connection closed by 192.168.5.2 port 51138 [preauth]
sshd-1 | Connection closed by 192.168.5.2 port 51144 [preauth]
sshd-1 | Connection closed by 192.168.5.2 port 51148 [preauth]
sshd-1 | Connection closed by 192.168.5.2 port 51770 [preauth]
I’ve had similar problems with making backintime profiles before. I THINK, but cannot really show, that it is something to do with me always using ed25519 keys and backintime cannot handle it. It keeps mentioning edcsa. But like I said, that is just my 2 pennies. I can easily change the key type to find out.
Meekly I returned to your instruction step 14 …
sshd-1 | Accepted publickey for backintime from 192.168.5.2 port 41168
That worked perfectly after first removing what the backintime profile creating attempt had entered into known_hosts:
arjen@NUC10i5:~$ ssh -i ~/.ssh/id_ed25519 -p 10022 backintime@192.168.5.55
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Offending ECDSA key in /home/arjen/.ssh/known_hosts:127
remove with:
ssh-keygen -f ‚/home/arjen/.ssh/known_hosts‘ -R ‚[192.168.5.55]:10022‘
Host key for [192.168.5.55]:10022 has changed and you have requested strict checking.
Host key verification failed.
arjen@NUC10i5:~$ ssh-keygen -f ‚/home/arjen/.ssh/known_hosts‘ -R ‚[192.168.5.55]:10022‘
# Host [192.168.5.55]:10022 found: line 127
/home/arjen/.ssh/known_hosts updated.
Original contents retained as /home/arjen/.ssh/known_hosts.old
arjen@NUC10i5:~$ ssh -i ~/.ssh/id_ed25519 -p 10022 backintime@192.168.5.55
The authenticity of host ‚[192.168.5.55]:10022 ([192.168.5.55]:10022)‘ can’t be established.
ED25519 key fingerprint is
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added ‚[192.168.5.55]:10022‘ (ED25519) to the list of known hosts.
Welcome to Alpine!
The Alpine Wiki contains a large amount of how-to guides and general
information about administrating Alpine systems.
See .
You can setup the system with the command: setup-alpine
You may change this message by editing /etc/motd.
backintime@2c97cdea1aa6:~$
All hunkydory now!
It is late … continuing with backintime tomorrow …
Thank you very much, CaCO3 (calcium carbonate 🙂
Hands-on experience is great!
P.S. IMO this solution is much better and cleaner than what I have seen suggested here and there and the previous homebrew stuff. It would be great if this docker thing can provide a basis for using rsync with ssh for off-site backup copying circumventing the restrictions UGOS places on rsync. Maybe it needs developing, but I have had no time to think it over and do testing.
BTW, immediately after you change a user from admin to general or vv., the corresponding passwd line shows the change in the group id. I think your instructions would benefit from having no contradictions about the group id. Your log has the correct GID 100 which reflects step 1, but in other places the GID is 10.
Congratulations!
I am glad it does not only work for me on my messed up system 🙂
Thanks for the hint about the GID, there was still one outdated screenshot.
I also added a note that the SSH key copying mechanism provided by BiT is not supported (it is shown when SSH expects a password).
One thing that still bugs me is the complicated way to add the public key. I think it would be possible to add it as a docker compose environment variable. But I would have to modify the docker image which was not written by me. With that solution, one would not even need to use SSH at all.
After changing the owner:group on /volume1/backintime in an ssh terminal session for my main user arjen, it is necessary to use sudo on
chmod 755 /volume2/backintime
as well. (User backintime being a non-admin user, one cannot login with that username to avoid using sudo.)
Having run those two commands with the expected result and after checking the compose text, redeploy ends in a message about authorized_keys (see below). It doesn’t say error, but it doesn’t look right.
I have not been able to locate /conf.d/ …. Below is where I’ve been looking from the ssh terminal session to my DXP2800:
arjen@DXP2800-5FD4:~$ ls -la /etc/ssh
total 625
drwxr-xr-x 1 root root 4096 Dec 29 12:16 .
drwxr-xr-x 1 root root 4096 Jan 16 21:05 ..
-rwxr-xr-x 1 root root 1786 Dec 23 15:24 force_command.sh
-rw-r–r– 1 root root 573928 Dec 23 15:24 moduli
-rwxrw-rw- 1 root root 1496 Jan 15 00:30 sftp_share.conf
-rw-r–r– 1 root root 1650 Dec 23 15:24 ssh_config
drwxr-xr-x 2 root root 3 Dec 23 15:32 ssh_config.d
-rw——- 1 root root 3255 Jan 15 00:30 sshd_config
-rw-r—– 1 root root 3255 Nov 6 22:28 sshd_config._bak
drwxr-xr-x 1 root root 4096 Jan 15 00:30 sshd_config.d
-rw——- 1 root root 505 Nov 21 2024 ssh_host_ecdsa_key
-rw-r–r– 1 root root 176 Nov 21 2024 ssh_host_ecdsa_key.pub
-rw——- 1 root root 411 Nov 21 2024 ssh_host_ed25519_key
-rw-r–r– 1 root root 96 Nov 21 2024 ssh_host_ed25519_key.pub
-rw——- 1 root root 2602 Nov 21 2024 ssh_host_rsa_key
-rw-r–r– 1 root root 568 Nov 21 2024 ssh_host_rsa_key.pub
arjen@DXP2800-5FD4:~$ ls -la /etc/ssh/ssh_config.d
total 8
drwxr-xr-x 2 root root 3 Dec 23 15:32 .
drwxr-xr-x 1 root root 4096 Dec 29 12:16 ..
arjen@DXP2800-5FD4:~$ ls -la /etc/ssh/sshd_config.d
total 25
drwxr-xr-x 1 root root 4096 Jan 15 00:30 .
drwxr-xr-x 1 root root 4096 Dec 29 12:16 ..
-rw——- 1 root root 444 Jan 15 00:30 high_crypt.conf
-rw-r–r– 1 root root 573 Dec 23 15:24 low_crypt.conf
-rw——- 1 root root 447 Oct 5 12:59 middle_crypt.conf
arjen@DXP2800-5FD4:~$
This is the log for the redeploy:
sshd-1 | [INFO] Applying configuration for ‚root‘ user …
sshd-1 | [INFO] disabled login for user ‚root‘
sshd-1 | [INFO] user ‚root‘ is now LOCKED
sshd-1 |
sshd-1 | [INFO] Applying configuration for additional users …
sshd-1 | [INFO] desired shell is /bin/bash
sshd-1 | [INFO] ‚backintime:1006:100‘
sshd-1 | [WARN] desired GID is already present in system. Using the present group-name – GID: ‚100‘ GNAME: ‚users‘
sshd-1 | [WARN] desired USER_NAME is already present in system. Skipping creation – USER_NAME: ‚backintime‘
sshd-1 | cp: omitting directory ‚/conf.d/authorized_keys/backintime‘
There is an authorized_keys directory in the shared folder /volume1/backintime with read and write access for user backintime, but the folder remains empty.
I can enable the container and it will say ’starting‘, but it ends up in a Not Running state:
‚Container – backintime-sshd Not Running‘
Nevertheless I tried to make a new backintime profile on my Linux Mint DE workstation as per your screenshots with port 10022 and an empty path, but for now it failed, which may not be so strange because of the directory being omitted and/or the container not running.
For comparison I have the jellyfin container which UGREEN set up. I don’t use jellyfin now, but the container is running.
There’s still something wrong here … As an experienced Docker user you perhaps notice it?
Right, I missed that 2nd „sudo“.
You will not find „/conf.d“ on your DXP directly, it is only contained in the docker container! There is no need to check the /etc/ssh of your DXP, since it is not involved in this approach!
To fiddle around in the container, you can use „ssh -i PATH/TO/YOUR/PRIVATE/SSH_KEY -p 10022 backintime@192.168.1.8″ once the SSH key is setup correctly. To access the container with a password instead of an SSH key, add the parameter „ROOT_PASSWORD=MyRootPW123“ to the environment section in the docker compose file, see https://github.com/caco3/docker-sshd?tab=readme-ov-file#authentication-as-root-by-password
As for the troubleshooting:
I think you placed the key file in the wrong folder. It must be placed in the docker project folder, eg.:
/volume1/docker/backintime-sshd/
├── authorized_keys
│ └── backintime
└── docker-compose.yaml
Please show me the output of „tree /volume1/docker/backintime-sshd/“ (or where your docker is installed).
Note:
The 2 warnings in the docker log can be ignored, I see them as well.
Previous message went lost …
There is a discrepancy between what you write (non-admin user) and the example where backintime has UID 10, not 100 like for non-admin.
I now tried both, but the thing doesn’t start and look like the jellyfin one I have (no input by myself in that one)
It didn’t get lost, but I had to unlock it first.
It might have the GID because it was originally an admin user.
But I just tested it with a new user „tester_normal“.
In /etc/passwd it is noted as „tester_normal:x:1007:100:UGREEN USER:/home/tester_normal:/usr/sbin/nologin“
Thus in docker-compose.yaml I wrote
services:
sshd:
image: caco3x/docker-sshd
environment:
- SSH_USERS=tester_normal:1007:100
ports:
- 10022:22
volumes:
- ./authorized_keys:/conf.d/authorized_keys
- type: bind
source: /volume2/backintime
target: /home/tester_normal/backintime
Make sure that the mounted folder (/volume2/backintime) has the right ownership. I had to run run „sudo chown tester_normal:users /volume2/backintime -R“ and „sudo chmod 755 /volume2/backintime“ on the host beforehand.
I have updated the page and added more information.
Please note that I changed the volume line „- ./authorized_keys:/conf.d/authorized_keys“ (removed the username behind it)!
Let me know if it works.
I changed the backintime user to an admin one and then tried with GID 10, too, but enabling the project doesn’t result in a running container, although the log only has warning about the GID already existing etc. I am very probably missing something essential here. Got to read about docker. I saw some videos by a Georgian lady called Nana about docker, but obviously I need to check them ’step by step‘ like the transistor radio kits from the 1950’s … That’s how old I am 😉
Hi,
I started to implement your instructions.
The non-admin user you suggest I’d create (backintime) is defined in /etc/passwd as follows:
backintime:x:1006:100:UGREEN USER:/home/backintime:/usr/sbin/nologin
However, in your compose configuration example it is in the admin group (10):
environment:
– SSH_USERS=backintime:1003:10
How should I interpret this?
(there are more messages when I try to ’start the container‘, but the UID needs to be solved first, I suppose.)
Thanks for the instructions. I’m sure they will get me somewhere …
– SSH_USERS=backintime:1003:10
must be replaced to
– SSH_USERS=backintime:1006:100
in your case
I tried to install brew, but the first two commands produced output that suggested it is not simple to go forward with it. Indeed somebody commented that I should replace UGOS with Debian …
How did you navigate past the sudo apt-get install …. command?
(see discussion here: https://ugreen-forum.de/forum/thread/1202-tut-homebrew-for-linux/#post30199)