OneDrive on NixOS using Docker
My NAS is a Atom based Thecus running NixOS. NixOS is a Linux distribution with a functional, as in functional programming, approach to package and configuration management. It contains many packages and services. In most cases enabling a new service is as easy as adding services.openssh.enable = true
to /etc/nixos/configuration.nix
.
Unfortunately skilion/onedrive, a D-lang based OneDrive client, is not available on NixOS and building it required a different version of the DMD compiler.
I was a bit lazy and also wanted to experiment with docker on NixOS so I decided to run skilion/onedrive as docker container on NixOS.
NATIVE PACKAGE AVAILABLE
Onedrive is now available as a native NixOS package.
Enabling Docker in NixOS
Enabling Docker on NixOS is as easy as adding the following to /etc/nixos/configuration.nix
:
1
2
3
4
5
# Enable Docker
virtualisation.docker.enable = true;
# Allow my regular user to control docker.
users.extraUsers.USER.extraGroups = [ "docker" ];
Setting up croc/onedrive
Finding the right Docker Image
First of all I had to find the right docker image on Docker Hub, the most popular image kukki/docker-onedrive is out of date, luckily croc/onedrive is more up to date.
Initialize the container
1
2
3
4
5
6
7
# All these commands are as USER, not root.
# Create some directories, where we going to store our data and some state & config
mkdir -p /home/USER/onedrive
mkdir -p /home/USER/onedrive-config
# Pull the image
docker pull croc/onedrive
Acquiring the access token
1
2
3
4
5
6
7
8
# Run it once, to acquire the access token
docker run -ti \
--name onedrive \
--user $UID:`id --group` \
-v /home/USER/onedrive-config:/config \
-v /home/USER/onedrive:/onedrive \
croc/onedrive
# Line 4 is important to run the container under our own user, instead of root.
The container will start, authorize the application by:
- open the URL (Authorize this app visiting)
- do the necessary steps (login on onedrive, etc…)
- paste the long URL after the login
The application will start syncing, as soon as it starts, you can quit the synchronization using CTRL-C
.
Running OneDrive as a SystemD service
Following some guidance of running Docker Containers on SystemD I adapted this to NixOS.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
systemd.services.docker-onedrive-USER = {
# Make sure docker is started.
after = [ "docker.service" ];
# To avoid race conditions
requires = [ "docker.service" ];
serviceConfig = {
# Pulling an image might take a lot of time. 0 turns of the timeouts
TimeoutStartSec = "0";
# Restart policy, other relevant options are:
# - no
# - on-failure
# Look at the man page:
# man systemd.service
Restart = "always";
};
# Let's stop the running container , remove the image.
# The "|| true" is used because systemd expects that a everything succeeds,
# while failure is sometimes expected (eg. container was not running).
# Pull the image, ideally a version would be specified.
preStart = ''
${pkgs.docker}/bin/docker stop docker-onedrive-USER || true;
${pkgs.docker}/bin/docker rm docker-onedrive-USER || true;
${pkgs.docker}/bin/docker pull croc/onedrive
'';
# Start the container.
script = ''
${pkgs.docker}/bin/docker run \
--name docker-onedrive-USER \
--user 2000:100 \
--log-driver none \
-v /home/USER/onedrive-config:/config \
-v /home/USER/onedrive:/onedrive \
croc/onedrive
'';
# When the systemd service stops, stop the docker container.
preStop = ''
${pkgs.docker}/bin/docker kill docker-onedrive-USER
'';
};
L31 ${pkgs.docker}
refers to the Nix docker package.
L32 --name docker-onedrive-USER
Give the running container a name.
L33 --user 2000:100
Set the UID & group id, use the same values as you used in Acquiring the access token.
L34 --log-driver none
dockerd logs the output of a container to systemd, while we also attach the systemd service ddirectly. This avoids duplicate log messages.
L35 -v /home/USER/onedrive-config:/config
bind the config directory.
L36 -v /home/USER/onedrive:/onedrive
bind the data directory.
L37 croc/onedrive
the container name.
Applying the changes we made.
NixOS configuration needs to be applied to take affect.
1
nixos-rebuild --switch
You can monitor the newly created service.
1
2
3
4
5
# Will show status, the latest log lines
systemd status docker-onedrive-USER.service
# The journal contains the full history
journalctl -u docker-onedrive-USER.service
Restarting the service is no different than any other systemd service
1
2
systemd restart docker-onedrive-USER.service
systemd stop docker-onedrive-USER.service
If we made a mistake, it’s very easy to revert to the previous NixOS generation.
1
nixos-rebuild --rollback
Conclusion
Warning
We are using an open-source, unofficial OneDrive client. Which might break, delete your data, corrupt your data, etc… Also trusting a third party docker container can come with risks, it might steal your credentials, etc.
Conclusion
Running Docker containers on NixOS works as a charm, using a few steps they are managed as if they were native systemd services. NixOS allows quick rollbacks and makes configuration management tools unnecessary.
The docker container used croc/onedrive could be made a lot smaller, by using the alpine image, and should be versioned.
The NixOS community is very active, mostly on GitHub and the mailing list.
In conclusion having OneDrive on my NAS means I can integrate it with my backup and snapshot flows.