All apps · 0 apps
TimeMachine
Docker app from moritzf's Repository
Overview
Readme
View on GitHubmbentley/timemachine
docker image to run Samba or AFP (netatalk) to provide a compatible Time Machine for MacOS
Image Tags
Multi-arch Tags
The following tags have multi-arch support for amd64 and arm64 and will automatically pull the correct tag based on your system's architecture:
latest, smb
Note: The afp tag has been deprecated in terms of new feature updates and is only available for amd64.
Date Specific Tags
The smb tags also have unique manifests that are generated daily. These are in the format smb-YYYYMMDD (e.g. - smb-20210730) and can be viewed on Docker Hub. Each one of these tags will be generated daily and is essentially a point in time snapshot of the smb tag's manifest that you can pin to if you wish. Please note that these tags will remain available on Docker Hub for 6 months and will not receive security fixes. You will need to update to newer tags as they are published in order to get updated images. If you do not care about specific image digests to pin to, I would suggest just using the smb tag.
Explicit Architecture Tags
These tags will explicitly pull the image for the listed architecture and are bit for bit identical to the multi-arch tags images.
amd64
latest-smb-amd64,smb-amd64- SMB image based off of alpine:latestafp,afp-amd64- AFP image based off of debian:jessie- Deprecated but still available; not being regularly built - This image may have unpatched security vulnerabilities
armv7l
Note: new armv7l images are no longer being built as I have deprecated that architecture.
latest-smb-armv7l,smb-armv7l- SMB image based off of alpine:latest for thearmv7larchitecture
arm64
latest-smb-arm64,smb-arm64- SMB image based off of alpine:latest for thearm64architecture
Warning: I would strongly suggest migrating to the SMB image as AFP is being deprecated by Apple and I've found it to be much more stable. I do not plan on adding any new features to the AFP based config and I switched the default image in the latest tag to the SMB variant on October 15, 2020.
To pull this image:
docker pull mbentley/timemachine:smb
Example usage for SMB
Note: If you update the TM_USERNAME value, that will change the path for the persistent volume. See persistent data path for more details.
Example usage with --net=host to allow Avahi discovery; with commonly used environment variables set to their default values:
docker run -d --restart=always \
--name timemachine \
--net=host \
-e TM_USERNAME="timemachine" \
-e TM_GROUPNAME="timemachine" \
-e PASSWORD="timemachine" \
-e TM_UID="1000" \
-e TM_GID="1000" \
-e SET_PERMISSIONS="false" \
-e VOLUME_SIZE_LIMIT="0" \
-v /path/on/host/to/backup/to/for/timemachine:/opt/timemachine \
--tmpfs /run/samba \
mbentley/timemachine:smb
Example usage with exposing ports without Avahi discovery; with commonly used environment variables set to their default values:
docker run -d --restart=always \
--name timemachine \
--hostname timemachine \
-p 137:137/udp \
-p 138:138/udp \
-p 139:139 \
-p 445:445 \
-e TM_USERNAME="timemachine" \
-e TM_GROUPNAME="timemachine" \
-e PASSWORD="timemachine" \
-e TM_UID="1000" \
-e TM_GID="1000" \
-e SET_PERMISSIONS="false" \
-e VOLUME_SIZE_LIMIT="0" \
-v /path/on/host/to/backup/to/for/timemachine:/opt/timemachine \
--tmpfs /run/samba \
mbentley/timemachine:smb
Kubernetes support
The images are also compatible with Kubernetes. Checkout timemachine-k3s.yaml as an example for running a TimeMachine backup server on a single-node k3s cluster running (on a Raspberry Pi 4).
Tips for Automatic Discovery w/Avahi
This works best with --net=host so that discovery can be broadcast. Otherwise, you will need to expose the above ports and then you must manually map the share in Finder for it to show up (open Finder, click Shared, and connect as smb://hostname-or-ip/TimeMachine with your TimeMachine credentials). Using --net=host only works if you do not already run Samba or Avahi on the host! Alternatively, you can use the SMB_PORT option to change the port that Samba uses. See below for another workaround if you do not wish to change the Samba port.
Known Issues
Processes fail to start; container has high CPU usage
If the container isn't starting and you're seeing logs like Failed to start message bus: Failed to bind socket, and possibly have other symptoms like seeing high CPU usage from the container, it could be that your are hitting the nofile ulimit. Make sure your compose file or docker run command have the nofile ulimits adjusted to increase the defaults. Check the examples in the README or the example compose files in this repository.
Unable to start the armv7l image
If you are running the armv7l image, you may see and error when trying to start the container:
s6-svscan: warning: unable to iopause: Operation not permitted
This is due to an issue with the libseccomp2 package. You have two options:
Disable seccomp for the container by adding the
--security-opt seccomp=unconfinedargument (this has security implications)Install a backported version of
libseccomp2:wget http://ftp.us.debian.org/debian/pool/main/libs/libseccomp/libseccomp2_2.5.1-1~bpo10+1_armhf.deb sudo dpkg -i libseccomp2_2.5.1-1~bpo10+1_armhf.deb
This issue has been observed on Raspberry Pi OS (formerly known as Raspbian) based on Debian 10 (Buster) but may also be found on other distros as they may commonly use the libseccomp2 package version 2.3.3-4.
Conflicts with Samba and/or Avahi on the Host
Note: If you are already running Samba/Avahi on your Docker host (or you're wanting to run this on your NAS), you should be aware that using --net=host will cause a conflict with the Samba/Avahi install. Raspberry Pi users: be aware that there is already an mDNS responder running on the stock Raspberry Pi OS image that will conflict with the mDNS responder in the container.
If your host is running Avahi, you can configure it to act as a reflector, and the container advertisements will be broadcast to your host network without using --net=host. To do this, edit the avahi config (/etc/avahi/avahi-daemon.conf) on the host:
- set
enable-reflector=yes - set
cache-entries-max=0- this prevents issues with Apple devices reporting duplicate names and adding/incrementing numbers in their name (references: https://blogs.thismonkey.com/?p=33 and https://community.ui.com/questions/mdns-reflector-help-computer-name-keeps-changing/180dd51f-a5b2-465c-88c2-6e85ab03c38a#answer/4732ed77-37aa-4f30-b992-cf99752e4f6a)
Then set the ADVERTISED_HOSTNAME environment variable in your container config to the mDNS hostname of your host, without the .local suffix.
As an alternative, you can use the macvlan driver in Docker which will allow you to map a static IP address to your container. If you have issues setting up Time Machine with the configuration, feel free to open an issue and I can assist - this is how I persoanlly run time machine.
- Create a
macvlanDocker network (assuming your local subnet is192.168.1.0/24, the default gateway is192.168.1.1, andeth0for the host's network interface):
docker network create -d macvlan --subnet=192.168.1.0/24 --gateway=192.168.1.1 -o parent=eth0 macvlan1
On devices such as Synology DSM, the primary network interface may be ovs_eth0 due to the usage of Open vSwitch. If you are unsure of your primary network interface, this command may help:
$ route | grep ^default | awk '{print $NF}'
eth0
The macvlan driver can use another network interface as the documentation states above but in cases where multiple network interfaces may exist and they might not all be connected, choosing the primary network interface is generally safe.
- Add
--network macvlan1and--ip 192.168.1.xto yourdocker runcommand where192.168.1.xis a static IP to assign to Time Machine
Example macvlan setup using docker-compose
services:
timemachine:
hostname: timemachine
mac_address: "AA:BB:CC:DD:EE:FF"
networks:
timemachine:
ipv4_address: 192.168.1.x
networks:
timemachine:
driver: macvlan
driver_opts:
parent: eth0
ipam:
config:
- subnet: 192.168.1.0/24
ip_range: 192.168.1.0/24
gateway: 192.168.1.1
hostname,mac_address, andipv4_addressare optional, but can be used to control how it is configured on the network. If not defined, random values will be used.- This config requires docker-compose version
1.27.0+which implements the compose specification.
Volume & File system Permissions
If you're using an external volume like in the example above, you will need to set the filesystem permissions on disk. By default, the timemachine user is 1000:1000.
The backing data store for your persistent time machine data must support extended file attributes (xattr). Remote file systems, such as NFS, will very likely not support xattrs. See #61 for more details. This image will check and try to set xattrs to a test file in /opt/${TM_USERNAME} to warn the user if they are not supported but this will not prevent the image from running.
Persistent Data Path
If you change the TM_USERNAME value, it will change the persistent data path from /opt/timemachine to /opt/<value-of-TM_USERNAME>. Failure to map this appropriately will lead to data being stored inside the container and not in the volume you have specified!
Default credentials
- Username:
timemachine - Password:
timemachine
Optional variables for SMB
| Variable | Default | Description |
|---|---|---|
ADVERTISED_HOSTNAME |
not set | Avahi will advertise the smb services at this hostname instead of the local hostname (useful in Docker without --net=host). Do not set this if you don't know what you're doing! |
CUSTOM_SMB_AUTH |
no |
set to yes, indicates that you want Samba to attempt to authenticate users using the NTLM Encrypted Password Response |
CUSTOM_SMB_CONF |
false |
indicates that you are going to bind mount a custom config to /etc/samba/smb.conf if set to true |
CUSTOM_SMB_PROTO |
SMB2 |
indicates that you want to allow another value from Samba Protocol List |
CUSTOM_USER |
false |
indicates that you are going to bind mount /etc/password, /etc/group, and /etc/shadow; and create data directories if set to true |
DEBUG_LEVEL |
1 |
sets the debug level for nmbd and smbd |
EXTERNAL_CONF |
not set | specifies a directory in which individual variable files, ending in .conf, for multiple users; see Adding Multiple Users & Shares for more info |
HIDE_SHARES |
no |
set to yes if you would like only the share(s) a user can access to appear |
MIMIC_MODEL |
TimeCapsule8,119 |
sets the value of time machine to mimic |
TM_USERNAME |
timemachine |
sets the username time machine runs as |
TM_GROUPNAME |
timemachine |
sets the group name time machine runs as |
TM_UID |
1000 |
sets the UID of the TM_USERNAME user |
TM_GID |
1000 |
sets the GID of the TM_GROUPNAME group |
PASSWORD |
timemachine |
sets the password for the timemachine user |
SET_PERMISSIONS |
false |
set to true to have the entrypoint set ownership and permission on the /opt/<username> in the container |
SHARE_NAME |
TimeMachine |
sets the name of the timemachine share to TimeMachine by default |
SHARE_PATH |
/opt/<TM_USERNAME> |
sets the path for the share data directory; useful when using EXTERNAL_CONF to place share data in a custom location |
TM_ENABLED |
yes |
set to no to disable Time Machine for this share (removes fruit:time machine and Avahi _adisk._tcp advertisement); useful with EXTERNAL_CONF to mix Time Machine and regular file shares |
SMB_INHERIT_PERMISSIONS |
no |
if yes, permissions for new files will be forced to match the parent folder |
SMB_NFS_ACES |
no |
value of fruit:nfs_aces; support for querying and modifying the UNIX mode of directory entries via NFS ACEs |
SMB_METADATA |
stream |
value of fruit:metadata; controls where the OS X metadata stream is stored |
SMB_PORT |
445 |
sets the port that Samba will be available on |
SMB_VFS_OBJECTS |
fruit streams_xattr |
value of vfs objects |
VOLUME_SIZE_LIMIT |
0 |
sets the maximum size of the time machine backup in MiB; a unit can also be passed (e.g. - 1 T). See the Samba docs under the fruit:time machine max size section for more details |
WORKGROUP |
WORKGROUP |
set the Samba workgroup name |
IGNORE_DOS_ATTRIBUTES |
false |
If set to true Samba will ignore DOS attributes. This is accomplished by setting store dos attributes, map hidden, map system, map archive and map readonly to no in the [global] section. |
EXTRA_SHARES |
not set | Comma-separated list of additional non-Time Machine shares in name:/path format (e.g. Files:/opt/files,Docs:/opt/docs); only used in single-user mode (not with EXTERNAL_CONF) |
Adding Extra Non-Time Machine Shares (without EXTERNAL_CONF)
If you want to expose one or more regular file shares alongside your Time Machine share, you can use the EXTRA_SHARES environment variable instead of setting up EXTERNAL_CONF files. This is especially useful for container orchestrators (Portainer, Runtipi, etc.) where shipping config files alongside the container is awkward.
[!NOTE] Each extra share is accessible only to the user defined by
TM_USERNAME. There is no way to set a differentvalid usersper extra share in this mode — useEXTERNAL_CONFif you need per-share user control.
Example docker-compose with an extra share
services:
timemachine:
image: mbentley/timemachine:smb
network_mode: host
environment:
- TM_USERNAME=timemachine
- PASSWORD=timemachine
- SHARE_NAME=TimeMachine
- VOLUME_SIZE_LIMIT=512000
- EXTRA_SHARES=Files:/opt/files
volumes:
- /path/to/timemachine:/opt/timemachine
- /path/to/files:/opt/files
tmpfs:
- /run/samba
restart: unless-stopped
ulimits:
nofile:
soft: 65536
hard: 65536
Multiple extra shares can be added as a comma-separated list: EXTRA_SHARES=Files:/opt/files,Docs:/opt/docs
Adding Multiple Users & Shares
In order to add multiple users who have their own shares, you will need to create a file for each user and put them in a directory. The file name must end in .conf or it will not be parsed and the contents must be environment variable formatted proper and include all of the values below in the example. Only VOLUME_SIZE_LIMIT can be empty if you do not want to set a quota.
Example EXTERNAL_CONF File
This is an example to create a user named foo. The EXTERNAL_CONF variable should point to the directory that contains the user definition files. Create multiple files with different attributes to create multiple users and shares.
foo.conf
TM_USERNAME=foo
TM_GROUPNAME=foogroup
PASSWORD=foopass
SHARE_NAME=foo
VOLUME_SIZE_LIMIT="1 T"
TM_UID=1000
TM_GID=1000
You can also optionally set SHARE_PATH and TM_ENABLED per share. For example, to create a regular (non-Time Machine) file share:
files.conf
TM_USERNAME=foo
TM_GROUPNAME=foogroup
PASSWORD=foopass
SHARE_NAME=Files
VOLUME_SIZE_LIMIT=
TM_UID=1000
TM_GID=1000
TM_ENABLED=no
SHARE_PATH=/opt/files
Example run command for EXTERNAL_CONF
This run command has the necessary path to where the external user files will be mounted (set in EXTERNAL_CONF) and the volume mount that matches the path specified in EXTERNAL_CONF.
Note: You will need to either bind mount /opt or each SHARE_NAME directory under /opt for each user.
docker run -d --restart=always \
--name timemachine \
--net=host \
--ulimit nofile=65536:65536 \
-e ADVERTISED_HOSTNAME="" \
-e CUSTOM_SMB_CONF="false" \
-e CUSTOM_USER="false" \
-e DEBUG_LEVEL="1" \
-e MIMIC_MODEL="TimeCapsule8,119" \
-e EXTERNAL_CONF="/users" \
-e HIDE_SHARES="no" \
-e TM_USERNAME="timemachine" \
-e TM_GROUPNAME="timemachine" \
-e TM_UID="1000" \
-e TM_GID="1000" \
-e PASSWORD="timemachine" \
-e SET_PERMISSIONS="false" \
-e SHARE_NAME="TimeMachine" \
-e SMB_INHERIT_PERMISSIONS="no" \
-e SMB_NFS_ACES="no" \
-e SMB_METADATA="stream" \
-e SMB_PORT="445" \
-e SMB_VFS_OBJECTS="fruit streams_xattr" \
-e VOLUME_SIZE_LIMIT="0" \
-e WORKGROUP="WORKGROUP" \
-v /path/on/host/to/backup/to/for/timemachine:/opt \
-v /path/on/host/to/user/file/directory:/users \
--tmpfs /run/samba \
mbentley/timemachine:smb
Using a password file
This is an example to using Docker secrets to pass the password via a file
password.txt
my_secret_password
Example docker-compose file
The follow example shows the key values required for in your compose file.
version: "3.3" # or greater
services:
timemachine:
# ...
environment:
- PASSWORD_FILE=/run/secrets/password
# ...
secrets:
- password
secrets:
password:
file: ./password.txt
AFP Examples and Variables
Click to expand
Example docker-compose usage for AFP
docker compose -f timemachine-compose.yml up -d
Example docker run usage for AFP
Example usage with --net=host to allow Avahi discovery to function:
docker run -d --restart=always \
--net=host \
--name timemachine \
-e CUSTOM_AFP_CONF="false" \
-e CUSTOM_USER="false" \
-e LOG_LEVEL="info" \
-e MIMIC_MODEL="TimeCapsule6,106" \
-e TM_USERNAME="timemachine" \
-e TM_GROUPNAME="timemachine" \
-e TM_UID="1000" \
-e TM_GID="1000" \
-e PASSWORD="timemachine" \
-e SET_PERMISSIONS="false" \
-e SHARE_NAME="TimeMachine" \
-e VOLUME_SIZE_LIMIT="0" \
-v /path/on/host/to/backup/to/for/timemachine:/opt/timemachine \
-v timemachine-netatalk:/var/netatalk \
-v timemachine-logs:/var/log/supervisor \
mbentley/timemachine:afp
Example usage with exposing ports without Avahi discovery:
docker run -d --restart=always \
--name timemachine \
--hostname timemachine \
-p 548:548 \
-p 636:636 \
-e CUSTOM_AFP_CONF="false" \
-e CUSTOM_USER="false" \
-e LOG_LEVEL="info" \
-e MIMIC_MODEL="TimeCapsule6,106" \
-e TM_USERNAME="timemachine" \
-e TM_GROUPNAME="timemachine" \
-e TM_UID="1000" \
-e TM_GID="1000" \
-e PASSWORD="timemachine" \
-e SET_PERMISSIONS="false" \
-e SHARE_NAME="TimeMachine" \
-e VOLUME_SIZE_LIMIT="0" \
-v /path/on/host/to/backup/to/for/timemachine:/opt/timemachine \
-v timemachine-netatalk:/var/netatalk \
-v timemachine-logs:/var/log/supervisor \
mbentley/timemachine:afp
This works best with --net=host so that discovery can be broadcast. Otherwise, you will need to expose the above ports and then you must manually map the share in Finder for it to show up (open Finder, click Shared, and connect as afp://hostname-or-ip/TimeMachine with your TimeMachine credentials).
Optional variables for AFP:
| Variable | Default | Description |
|---|---|---|
CUSTOM_AFP_CONF |
false |
indicates that you are going to bind mount a custom config to /etc/netatalk/afp.conf if set to true |
CUSTOM_USER |
false |
indicates that you are going to bind mount /etc/password, /etc/group, and /etc/shadow; and create data directories if set to true |
LOG_LEVEL |
info |
sets the netatalk log level |
MIMIC_MODEL |
TimeCapsule6,106 |
sets the value of time machine to mimic |
TM_USERNAME |
timemachine |
sets the username time machine runs as |
TM_GROUPNAME |
timemachine |
sets the group name time machine runs as |
TM_UID |
1000 |
sets the UID of the TM_USERNAME user |
TM_GID |
1000 |
sets the GID of the TM_GROUPNAME group |
PASSWORD |
timemachine |
sets the password for the timemachine user |
SET_PERMISSIONS |
false |
set to true to have the entrypoint set ownership and permission on /opt/timemachine |
SHARE_NAME |
TimeMachine |
sets the name of the timemachine share to TimeMachine by default |
VOLUME_SIZE_LIMIT |
0 |
sets the maximum size of the time machine backup in MiB (mebibyte) |
Thanks for odarriba and arve0 for their examples to start from.
Install TimeMachine on Unraid in a few clicks.
Find TimeMachine in Community Apps on your Unraid server, review the template, and click Install. Unraid handles the Docker app or plugin setup from the published template.
Requirements
Granting Permissions to write to the directory can be achieved by executing the following command on the host (Unraid): sudo chown -R 1000:1000 /mnt/user/timemachine/
The backing data store for your persistent time machine data must support extended file attributes (xattr). Usually for shares in the Unraid Array this is not a problem. Remote file systems, such as NFS, will very likely not support xattrs. This image will check and try to set xattrs to a test file in /opt/${TM_USERNAME} to warn the user if they are not supported but this will not prevent the image from running.
Also note that if you change the User Name (TM_USERNAME) value that it will change the data path for backup data inside of the container from /opt/timemachine to /opt/value-of-TM_USERNAME.
Categories
Download Statistics
Total Downloads Over Time
Related apps
Explore more like this
Explore allLinks
Details
mbentley/timemachineRuntime arguments
- Network
br0- Shell
sh- Privileged
- false
- Extra Params
--hostname timemachine
Template configuration
Directory to store the time machine backups. If you change the User Name (TM_USERNAME) value that it will change the data path from /opt/timemachine to /opt/value-of-TM_USERNAME.
- Target
- /opt/timemachine
- Value
- /mnt/user/timemachine/
Limits the reported disksize, thus preventing Time Machine from using the whole real disk space for backup. The option takes a number plus an optional unit (e.g. 1 T for 1 Terrabyte). IMPORTANT: This is an approximated calculation that only takes into account the contents of Time Machine sparsebundle images. Therefore you MUST NOT use this volume to store other content when using this option, because it would NOT be accounted. The calculation works by reading the band size from the Info.plist XML file of the sparsebundle, reading the bands/ directory counting the number of band files, and then multiplying one with the other.
- Target
- VOLUME_SIZE_LIMIT
- Default
- 1 T
- Value
- 1 T
sets the username time machine runs as
- Target
- TM_USERNAME
- Value
- timemachine
sets the password for the timemachine user. The default value is Z92efVNcokU26x.
- Target
- PASSWORD
- Default
- Z92efVNcokU26x
- Value
- Z92efVNcokU26x
Avahi will advertise the smb services at this hostname instead of the local hostname
- Target
- ADVERTISED_HOSTNAME
- Value
- timemachine
indicates that you are going to bind mount a custom config to /etc/samba/smb.conf if set to true
- Target
- CUSTOM_SMB_CONF
- Default
- false
- Value
- false
indicates that you are going to bind mount /etc/password, /etc/group, and /etc/shadow; and create data directories if set to true
- Target
- CUSTOM_USER
- Default
- false
- Value
- false
sets the debug level for nmbd and smbd
- Target
- DEBUG_LEVEL
- Default
- 1
- Value
- 1
sets the value of time machine to mimic (e.g. TimeCapsule8,119 or TimeCapsule6,116)
- Target
- MIMIC_MODEL
- Default
- TimeCapsule8,119
- Value
- TimeCapsule8,119
specifies a directory in which individual variable files, ending in .conf. In order to add multiple users who have their own shares, you will need to create a file for each user and put them in a directory.
- Target
- EXTERNAL_CONF
set to yes if you would like only the share(s) a user can access to appear
- Target
- HIDE_SHARES
- Default
- no
- Value
- no
sets the group name time machine runs as
- Target
- TM_GROUPNAME
- Default
- timemachine
- Value
- timemachine
sets the UID of the Executing User (TM_USERNAME)
- Target
- TM_UID
- Default
- 1000
- Value
- 1000
set to true to have the entrypoint set ownership and permission on the /opt/ in the container
- Target
- SET_PERMISSIONS
- Default
- false
- Value
- false
if yes, permissions for new files will be forced to match the parent folder
- Target
- SMB_INHERIT_PERMISSIONS
- Default
- no
- Value
- no
value of fruit:nfs_aces; support for querying and modifying the UNIX mode of directory entries via NFS ACEs
- Target
- SMB_NFS_ACES
- Default
- yes
- Value
- yes
value of fruit:metadata; controls where the OS X metadata stream is stored
- Target
- SMB_METADATA
- Default
- stream
- Value
- stream
sets the port that Samba will be available on
- Target
- SMB_PORT
- Default
- 445
- Value
- 445
value of vfs objects
- Target
- SMB_VFS_OBJECTS
- Default
- acl_xattr fruit streams_xattr
- Value
- acl_xattr fruit streams_xattr
set the SMB workgroup name
- Target
- WORKGROUP
- Default
- WORKGROUP
- Value
- WORKGROUP
sets the GID of the TM_GROUPNAME group
- Target
- TM_GID
- Default
- 1000
- Value
- 1000
sets the name of the timemachine share to.
- Target
- SHARE_NAME
- Default
- TimeMachine
- Value
- TimeMachine